ри написании процедуры переведения целого в строку столкнулся со следующей проблемой - если пользоваться командой DIV, то делимое берется из dx:ax, делитель указывается, остаток записывается dx, частное в ax. Отсюда и возникает ожидаемая проблема перевода dword в строку: Если (dx:ax)*делитель > 65535, то частное не поместится а ах, возникнет integer overflow. Код (Text): format PE GUI 4.0 entry start include '%include%\win32a.inc' section '.data' data readable writeable a dd 655360 buf db ?,?,?,?,?,?,?,0 ; c-string section '.code' code readable executable start: mov esi,[a] mov ecx,7 mov edi,buf call IntToStrA invoke MessageBox,NULL,buf,buf,0 invoke ExitProcess,ecx proc IntToStrA ; in: esi - integer, ecx - buf lenght, edi - buffer; out: ecx - symbols count push eax push ebx push edx mov ebx,ecx xor ecx,ecx ; counter mov bx,10 mov eax,esi .next: cmp eax,0 jz .prn push eax and eax,0xFFFF0000 shr eax,16 mov dx,ax ; high word of eax pop eax and eax,0x0000FFFF div bx ; <dx:ax> / bx = ax(ch) + dx (os) ; exeption:integer overflow add dx,'0' push dx inc ecx cmp ebx, ecx je .prn ; max buffer jmp .next .prn: jcxz .prn0 xor edx,edx .nx: pop ax mov [edi+edx],al inc edx loop .nx mov ecx,edx jmp .exit .prn0: mov [edi],byte '0' mov ecx,1 .exit: pop edx pop ebx pop eax ret endp section '.idata' import data readable writeable library kernel32,'KERNEL32.DLL',\ user32,'USER32.DLL' include 'api\kernel32.inc' include '%include%\api\user32.inc' Как решить данную проблему?
1) Используй edx:eax 2) судя по фрагменту программы - используется MessageBox и ExitProcess - поэтому для перевода dword в строку логично использовать wsprintf 3)также прекрасно переводится при использовании fpu Код (Text): .data Data_Int64 dq ?;64-разрядное число Data_BCD dt ?;число в BCD-формате .code ... IntToStr proc or edx,edx ;число 64-разрядное? jnz b1 cmp eax,10 ;число меньше 10? jae b0 add al,30h stosb ret b0: cmp eax,100 ;число меньше 100? jae b1 aam add ax,3030h xchg ah,al stosw ret b1: push ecx mov dword ptr Data_Int64,eax;младшая часть 64-разрядного числа mov dword ptr Data_Int64+4,edx;старшая часть 64-разрядного числа fninit ;сброс сопроцессора fild Data_Int64 ;загрузить число в двоичном коде fbstp Data_BCD ;извлечь число в коде BCD mov ecx,9 ;в десятом байте информация о знаке числа b2: cmp byte ptr [ecx-1+Data_BCD],0 jnz b3 loop b2 ;пропускаем незначащие (нулевые) разряды слева b3: mov al,byte ptr [ecx-1+Data_BCD];загружаем первую значащую пару разрядов cmp al,9 ;если в старшей тетраде 0 - пропустить старшую тетраду ja b4 add al,30h ;младшую тетраду переводим в ASCII stosb dec ecx b4: mov ah,byte ptr [ecx-1+Data_BCD];распаковываем остальные разряды числа shr ax,4 ;выделяем старшую и младшую тетрады shr al,4 add ax,3030h ;переводим в ASCII-код xchg ah,al stosw loop b4 pop ecx ret IntToStr endp 4) Либо дели по частям - в Юрове "Assembler - практика" описан алгоритм деления n- байтного числа на m-байтное 5) использузуй SSE и MMX инструкции
ну вообще есть разные div'ы. div [byte]: ax / [byte] = al : dl div [word]: dx:ax / [word] = ax : dx div [dword]: edx:eax / [dword] = eax : edx как уже сказали можно заюзать деление edx:eax на двойное слово