Переведение целых в строку, DIV

Тема в разделе "WASM.BEGINNERS", создана пользователем SpiritFire, 6 май 2008.

  1. SpiritFire

    SpiritFire New Member

    Публикаций:
    0
    Регистрация:
    21 янв 2008
    Сообщения:
    31
    ри написании процедуры переведения целого в строку столкнулся со следующей проблемой - если пользоваться командой DIV, то делимое берется из dx:ax, делитель указывается, остаток записывается dx, частное в ax.
    Отсюда и возникает ожидаемая проблема перевода dword в строку:
    Если (dx:ax)*делитель > 65535, то частное не поместится а ах, возникнет integer overflow.
    Код (Text):
    1. format PE GUI 4.0
    2. entry start
    3.  
    4. include '%include%\win32a.inc'
    5.  
    6. section '.data' data readable writeable
    7.   a dd 655360
    8.   buf db ?,?,?,?,?,?,?,0      ; c-string
    9.  
    10. section '.code' code readable executable
    11.   start:
    12.         mov esi,[a]
    13.         mov ecx,7
    14.         mov edi,buf
    15.         call IntToStrA
    16.         invoke MessageBox,NULL,buf,buf,0
    17.         invoke  ExitProcess,ecx
    18.  
    19. proc IntToStrA
    20. ; in: esi - integer, ecx - buf lenght, edi - buffer; out: ecx - symbols count
    21.         push eax
    22.         push ebx
    23.         push edx
    24.         mov ebx,ecx
    25.  
    26.         xor ecx,ecx     ; counter
    27.         mov bx,10
    28.  
    29.         mov eax,esi
    30. .next:  cmp eax,0
    31.         jz .prn
    32.         push eax
    33.         and eax,0xFFFF0000
    34.         shr eax,16
    35.         mov dx,ax       ; high word of eax
    36.         pop eax
    37.         and eax,0x0000FFFF
    38.         div bx             ; <dx:ax> / bx = ax(ch) + dx (os) ; exeption:integer overflow
    39.         add dx,'0'
    40.         push dx
    41.         inc ecx
    42.         cmp ebx, ecx
    43.         je .prn                 ; max buffer
    44.         jmp .next
    45. .prn:
    46.         jcxz .prn0
    47.         xor edx,edx
    48. .nx:    pop ax
    49.         mov [edi+edx],al
    50.         inc edx
    51.         loop .nx
    52.         mov ecx,edx
    53.         jmp .exit
    54. .prn0:
    55.         mov [edi],byte '0'
    56.         mov ecx,1
    57. .exit:
    58.         pop edx
    59.         pop ebx
    60.         pop eax
    61.         ret
    62. endp
    63.  
    64. section '.idata' import data readable writeable
    65.  
    66.   library kernel32,'KERNEL32.DLL',\
    67.           user32,'USER32.DLL'
    68.  
    69.   include 'api\kernel32.inc'
    70.   include '%include%\api\user32.inc'
    Как решить данную проблему?
     
  2. Mikl_

    Mikl_ New Member

    Публикаций:
    0
    Регистрация:
    14 ноя 2006
    Сообщения:
    907
    1) Используй edx:eax
    2) судя по фрагменту программы - используется MessageBox и ExitProcess - поэтому для перевода dword в строку логично использовать wsprintf
    3)также прекрасно переводится при использовании fpu
    Код (Text):
    1. .data
    2. Data_Int64   dq ?;64-разрядное число
    3. Data_BCD     dt ?;число в BCD-формате
    4. .code
    5. ...
    6. IntToStr proc
    7.             or edx,edx      ;число 64-разрядное?
    8.     jnz b1
    9.     cmp eax,10  ;число меньше 10?
    10.              jae b0
    11.     add al,30h
    12.     stosb
    13.              ret
    14. b0: cmp eax,100    ;число меньше 100?
    15.     jae b1
    16.     aam
    17.     add ax,3030h
    18.     xchg ah,al
    19.     stosw
    20.     ret
    21. b1: push ecx
    22.     mov dword ptr Data_Int64,eax;младшая часть 64-разрядного числа
    23.     mov dword ptr Data_Int64+4,edx;старшая часть 64-разрядного числа
    24.     fninit          ;сброс сопроцессора
    25.     fild Data_Int64     ;загрузить число в двоичном коде
    26.     fbstp Data_BCD      ;извлечь число в коде BCD
    27.     mov ecx,9               ;в десятом байте информация о знаке числа
    28. b2:     cmp byte ptr [ecx-1+Data_BCD],0
    29.     jnz b3        
    30.     loop b2         ;пропускаем незначащие (нулевые) разряды слева
    31. b3:    mov al,byte ptr [ecx-1+Data_BCD];загружаем первую значащую пару разрядов
    32.         cmp al,9  ;если в старшей тетраде 0 - пропустить старшую тетраду
    33.     ja b4
    34.     add al,30h      ;младшую тетраду переводим в ASCII
    35.     stosb
    36.     dec ecx
    37. b4:     mov ah,byte ptr [ecx-1+Data_BCD];распаковываем остальные разряды числа
    38.     shr ax,4            ;выделяем старшую и младшую тетрады
    39.     shr al,4
    40.     add ax,3030h        ;переводим в ASCII-код
    41.     xchg ah,al
    42.     stosw
    43.     loop b4
    44.     pop ecx
    45.              ret
    46. IntToStr    endp
    4) Либо дели по частям - в Юрове "Assembler - практика" описан алгоритм деления n- байтного числа на m-байтное
    5) использузуй SSE и MMX инструкции
     
  3. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    ну вообще есть разные div'ы.
    div [byte]: ax / [byte] = al : dl
    div [word]: dx:ax / [word] = ax : dx
    div [dword]: edx:eax / [dword] = eax : edx
    как уже сказали можно заюзать деление edx:eax на двойное слово
     
  4. Y_Mur

    Y_Mur Active Member

    Публикаций:
    0
    Регистрация:
    6 сен 2006
    Сообщения:
    2.494
  5. Sol_Ksacap

    Sol_Ksacap Миша

    Публикаций:
    0
    Регистрация:
    6 мар 2008
    Сообщения:
    623
    Поправлю Great ради Великой справедливости:
    div [byte]: ax / [byte] = al : ah
     
  6. SpiritFire

    SpiritFire New Member

    Публикаций:
    0
    Регистрация:
    21 янв 2008
    Сообщения:
    31
    Большое спасибо, в справочнике про dword не нашел.