2016-08-23 4 views
0

Я хочу получить два номера и сделать деление. Но он продолжает бросать исключение Float Point, поэтому я использовал gdb для отладки, и я обнаружил, что когда я храню значение rax, его высокие биты «повреждены».NASM mov работает неправильно

Когда [num] - 20d, 0x2800000014 хранится в rax.

Когда [num] 40d хранится 0x1400000028.

Я предполагаю, что некоторые из его высоких бит загружаются (?), Когда я их храню. В чем проблема?

section .data 
    in:  db "%d %d", 0 
    len: equ $-in 

section .bss 
    num: resd 2 

section .text 

main: 
    mov  rdi, in 
    mov  rsi, num 
    mov  rdx, num + 4 
    xor  rax, rax 
    call scanf 

    mov  rax, [num] ; ------------- here 
    mov  rdx, [num + 4] 
    idiv rdx 

    ... 

    xor  rax, rax 
    ret 

ответ

1

Вы сканирования в течение двух int с, и они хранятся в виде двух 32-битных целых чисел (4 байта друг от друга), начиная с адреса num.

Следовательно, когда вы пытаетесь читать 64 бита из этого места, вы получаете оба 32-битных значения. 0x14 == 20, а 0x28 - другое введенное вами значение.

Вы должны быть в состоянии заменить mov rax, [num] на mov eax, [num] (и аналогичным образом для rdx). Это автоматически очистит наиболее значимые 32 бита этих регистров.


Обратите внимание, что IDIV r/m64 делит RDX:EAX (128-битный octaword, образованный rdx и rax) с помощью делителя.
Так что не стоит использовать rdx в качестве делителя, так как это означает, что вы разделите 0xkkkkkkkkkkkkkkkkmmmmmmmmmmmmmmmm на 0xkkkkkkkkkkkkkkkk, давая вам коэффициент 0x0000000000000001nnnnnnnnnnnnnnnn. Поскольку допустимый диапазон для частного составляет −2^63 до 2^63 − 1, вы получите ошибку Divide из-за коэффициента вне диапазона.


TL; др: вы должны быть в состоянии это исправить, изменив 3 строки кода после call scanf на:

mov  eax, [num] 
cqo      ; sign-extend rax into rdx 
mov  ebx, [num + 4] ; <-- note, ebx instead of edx 
idiv rbx    ; <-- note, rbx instead of rdx 

Или, так как ваш дивиденд и делитель 32-бит, вы можно использовать IDIV r/m32, который будет likely be faster:

mov  eax, [num] 
cdq      ; sign-extend eax into edx 
mov  ebx, [num + 4] 
idiv ebx    

(cdq/cqo наполняющий edx/rdx со знаком-битом eax/rax)