На C я делал с помощью _itoa , но в масме её не нашёл поэтому начал писать сам... вот что получилось: CreateString proc NumberWORD push ebx add esp,8 push Number pop ebx xor ecx,ecx Loop1: mov eax,ebx cmp ecx,4 jz Loop2 cmp ecx,0 jz ECX0 cmp ecx,1 jz ECX1 cmp ecx,2 jz ECX2 jmp ECX3 ECX0: shl eax,28 shr eax,28 add eax,48d mov edx,eax jmp INC_ECX ECX1: shl eax,24 shr eax,28 add eax,48d mov dh,al jmp INC_ECX ECX2: shl eax,20 shr eax,28 add eax,48d rol edx,16 mov dh,al jmp INC_ECX ECX3: shl eax,16 shr eax,28 add eax,48d mov dl,al rol edx,16 INC_ECX: inc ecx jmp Loop1 Loop2: pop ebx ret CreateString endp конечно, надо доделать, но по сути правильно... вопрос в другом... вот есть у меня EDX=30303030h это по ASCII : "0000" КАК мне это загнать в строку если сделать buffer db 10 dup(0) то не работает... как мне добавить в строку? или добавить "0" в конец??
если есть буфер buffer db 10 dup(0) то EDX=30303030h сохраняется в буфер так: mov dword ptr[buffer],edx. Причем младший байт edx(dl) будет прописан по младшему адресу буфера. Т.е. например если edx = 30313233h, ecx = 64636261h то при mov dword ptr[buffer],edx mov dword ptr[buffer+4],eсx в буфер будет записана строка "3210abcd".
Код (Text): ;===================================================================== ============== ; Процедура перевода dword - числа в decimal-строку. Выходная строка ; помещается в буфер lpOutString: '-1234567890',0 ; Возвращаемое значение: нет .data r_divisor dd -858993459 .code _dwtostr proc dwDword:DWORD, lpOutString:DWORD option prologue : none option epilogue : none push esi push edi mov edi,[esp+16] ;lpOutString mov esi,[esp+12] ;dwDword cmp esi,0 jg _loop jz _zero neg esi mov byte ptr[edi],2Dh inc edi inc dword ptr[esp+16] ;lpOutString align 16 _loop: mov eax,esi mul r_divisor shr edx,3 mov ecx,edx lea ecx,[ecx*4+ecx] add ecx,ecx neg ecx add ecx,esi mov byte ptr[edi],30h or [edi],cl mov esi,edx test edx,edx lea edi,[edi+1] jnz _loop @@: mov byte ptr[edi],0 mov esi,[esp+16] align 16 @@: dec edi mov al,[esi] mov dl,[edi] mov [edi],al mov [esi],dl inc esi cmp esi,edi jl @B pop edi pop esi retn 8 _zero: mov word ptr[edi],30h pop edi pop esi retn 8 option prologue : prologuedef option epilogue : epiloguedef _dwtostr endp
спасибо, конечно, но что элементарно означата mov dword ptr [],eax ? под масм работает? а почему вот тут: mov dword ptr [buffer], edx mov byte ptr [buffer+4], 0 потом только [buffer+4] ведь edx 32-бита а что в последнем примере означатает: align 17 ? @@ ? option prologue? option epilogue? почему именно mov edi,[esp+16] почему EDI, и почему esp+16 а не допустим комбинация push dwDword pop edi а что значит retn 8 ??
Это значит: записать дворд (4 байта), содержащийся в eax, в 4 ячейки, начинающиеся с адреса, указанного внутри квадратных скобок. В каждую ячейку помещается 1 байт (или 8 бит). mov dword ptr [buffer],eax ;buffer - адрес, с которого начинается твой буфер. Например 403000h ;биты 0-7 (это al) помещаются по адресу 403000h ;биты 8-15 (это ah) помещаются по адресу 403001h ;биты 16-23 помещаются по адресу 403002h ;биты 24-31 помещаются по адресу 403003h здесь также 32 бита edx (или 4 байта) записываются в 4 ячейки размером 1 байт (8 бит). О том, что записываться будет 4 байта, указывает приставка dword. После этого записывается 0 в одну ячейку (1 байт). Это указывается приставкой byte Т.е. сколько будет записываться и в сколько ячеек, указывается в команде при помощи приставки dword/byte ptr. а что в последнем примере означатает: align 17 ? @@ ? option prologue? option epilogue? align 16 - это указание компилятору, что инструкции, следующие после этой директивы, нужно расположить по адресу, кратному 16. @@ - это метка. Переход на эту метку осуществляется так: jmp @B или jmp @F. В первом случае переход будет на ближайшую метку @@, находящуюся перед командой jmp @B, во втором случае - на ближайшую метку @@, находящуюся после jmp @F. Т.е. @B - это Backward, @F - Forward. option prologue/option epilogue - это директивы для компилятора, тебе они не нужны. Процедура вызывается так: Код (Text): push offset buffer ;в вершине стека [esp] - адрес буфера mov eax,1234567 push eax ;в [esp]- число для преобразования, ;адрес буфера переместился в [esp+4] call _dwtostr ;в [esp]- адрес, куда возвращаться из функции ;число для преобразования переместилось в [esp+4] ;буфер переместился в [esp+8] и когда начинается выполнение функции преобразования, первые две команды в ней - это команды сохранения регистров esi/edi. push esi push edi каждая команда ложит регистр в вершину стека, при этом проталкивая уже лежащие в стеке параметры каждый раз на 4 байта. Т.е. push esi и push edi сдвинут вершину стека на 8 байт. При этом параметры, которые передавались в функцию, тоже сместятся на 8 байт, и будут находиться: число для преобразования - в [esp+12] адрес буфера для формирования выходной строки - в [esp+16] поэтому и mov edi,dword ptr[esp+16] - в edi загружается адрес буфера. А вообще, на сайте есть для начинающих статьи о низкоуровневом программировании, возьми и почитай их. Там всё разжёвано подробно. С несложными примерчиками.