2016-11-27 13 views
1

У меня есть уравнение, которое я хочу смоделировать на языке ассемблера. Я написал следующий код, который синтаксически корректен, но приводит к неправильным результатам в регистре. Конечный результат должен быть сохранен в регистре DX. Уравнение Я моделирование:Неправильный расчет математического уравнения в языке Assembly (Intel)

DX = (AX + (AX -1) + 2 * (AX +2))/2

Ниже приведен код на языке ассемблера для микропроцессора Intel:

[org 0x0100] 
      jmp start 

number:   db 02 
multiplicand: db 0 
multiplier:  db 0 
multiResult: dw 0 
squareResult: dd 0 


square:  mov [multiplicand], AX 
      mov [multiplier], AX 
      call multi 
      mov AX, [multiResult] 
      mov [squareResult], AX 
      ret 


multi:   mov CL, 8 
       mov BX, [multiplicand] 
       mov DX, [multiplier] 

carryCheck:  shr BX, 1 
       jnc skip 

       add [multiResult], BX 


skip:   shl BX, 1 
       dec CL 
       jnz carryCheck 
       ret 


start:   mov AX, [number] 
       call square 
       mov DX, [squareResult] 
       sub byte[number], 1 
       add DX, AX 
       add byte[number], 2 
       mov AX, [number] 
       mov [multiplicand],AX 
       mov byte[multiplier], 2 
       call multi 
       add DX, [multiResult] 
       shr DX, 1     ; division by 2 

      mov AX, 0x4c00    ;ending program 
      int 0x21 
+2

Когда вы используете отладчик для выполнения кода, вы не можете определить место, где оно не удается? –

+1

У вас есть только хранилище байтов 'db', но чтение и запись' AX' и других 16-разрядных регистров: столкновение. 'db' ==>' dw'. –

+1

Почему вы не используете комментарии в своем ассемблере? –

ответ

1

Вы делаете это способом слишком сложно. Во-первых, упростить выражение тот, который легче вычислить

(AX*AX + (AX-1) + 2 * (AX+2))/2; 
(AX*AX + AX + 2*AX - 1 + 2)/2 
(AX*AX + 3*AX + 1)/2 
(AX*(AX+3) + 1)/2 

Это легко и просто реализовать:

mov dx, ax 
add dx, 3  ; dx = ax+3 

mul dx   ; dx:ax = ax * (ax+3) 

inc ax   ; ignore the high-half of the mul result in DX. 
shr ax, 1 

mov dx, ax  ; apparently you want the result in DX? 

Или вы должны держать 32-разрядные временные переменные? Если это так, используйте ADD/ADC для добавления 1 в DX: AX. Если вы используете emu8086 или что-то в этом роде, вы не можете использовать SHRD для переключения бит из DX в AX. Таким образом, вы можете использовать SHR для смещения бит DX и RCR, чтобы сдвинуть этот бит в AX.

Вам также необходимо сохранить выполнение с AX + 3, если вы сделаете это так.


BTW, вы можете легко спросить компилятор для идей. Однако gcc действительно не делает чистую 16-битную, а с 32-битным unsigned компиляцией в 32-битном режиме он использует LEA способами, которые не поддерживают 16-битные режимы адресации. Но вот what I tried on Godbolt.


Если вы хотите исправить исходный код, используйте отладчик. IDK, почему вы разветвляетесь на что-либо или используете память для чего-либо, и комментариев нет.

0

На этикетке carryCheck: инструкция shr BX, 1 должна быть shr DX, 1.

+0

Как отмечено в комментариях Weather Vane, существует также вероятность изменения переменной, когда значения слов записываются в адреса с байтами с разнесенными метками. Код (как написано) записывает правильные значения в адреса, но если порядок двух команд «mov» на метке «square:» был отменен, результат был бы неправильным). –

 Смежные вопросы

  • Нет связанных вопросов^_^