Инструкция IDIVQ работает странно.,,16 мод 100 = 0? - PullRequest
0 голосов
/ 21 мая 2019

Я хочу проверить по модулю значение деления 1 ~ 1000 на 100 с языком ассемблера x86-64.

Дело в том, что инструкция 'IDIVQ' работает странно, и я не понимаю, почему.

Вот мой код


.L0:
  ##dividend in %rax
  ##divider in %rsi
  ##modulo in %rdx

  pushq   %rax      # store dividend
  movq  $0x00, %rdx # initialize %rdx
  idivq   %rsi      # divide %rax by %rsi , modulo in  %rdx
  cmpq  $0x00, %rdx # if divided
  je   .L1


.L1:
  popq %rax   # retrieve dividend
  inc  %rax   # increment
  'When dividend == 1000, return'
  jmp  .L0


На GDB это похоже на


(gdb) p $rax
$7 = 16
(gdb) p $rsi
$8 = 100
(gdb) step
77    idivq   %rsi        # divide %rax by %rsi , modulo in  %rdx
(gdb) step
78    cmpq  $0x00, %rdx # if divided
(gdb) p $rsi
$9 = 100
(gdb) p/x $rax
$11 = 0x28f5c28f5c28f5c
(gdb) p $rdx
$12 = 0

Кто-нибудь подскажет, почему это происходит?

На данный момент я знаю, что инициализация% rdx имеет значение. когда я

movq $0x01, %rdx
idivq %rsi

Результат изменяется, но совершенно неверен, так как все они находятся на расстоянии 1 от правильного ответа

когда я ставлю

movq $0x1000, %rdx
idivq %rsi

приводит к ошибке сегментации.

1 Ответ

2 голосов
/ 21 мая 2019

Вы не запускаете код, который вы показываете, или ваш процессор сломан (маловероятно).

7     idivq   %rsi      # divide %rax by %rsi , modulo in  %rdx
(gdb) p $rax
$1 = 16
(gdb) p $rsi
$2 = 100
(gdb) si
8     cmpq  $0x00, %rdx # if divided
(gdb) p $rax
$3 = 0
(gdb) p $rdx
$4 = 16

Да, вам нужно обнулить rdx, потому что это верхние 64 бита дивиденда.

...