Сравните два числа в сборке Intel x86 (nasm)

У меня есть следующий код сборки:

%include 'rw32.inc'

[segment .data use32]  

a dd 2.0
b dd 1.0  
[segment .code use32]

prologue                ; macro -- inicialization
  fld dword [a]
  fld dword [b]
  fcom
  jc greater
  jmp less
greater:
  fxch
less:
  call WriteDouble
  call WriteNewLine
  epilogue                ; macro -- termination

rw32.inc — это служебная библиотека, включающая инициализацию и завершение программы, а также другие функции. WriteDouble — выводит на экран st0 WriteNewLine — просто вставляет новую строку.

и я хочу, чтобы это сравнило числа «a» и «b» и напечатало большее. Моя логика такова: получить оба числа в стеке. По fcom ставим флаги. Если флаг переноса равен 1, число «а» больше, поэтому его нужно переключить с помощью «b», чтобы он находился на вершине стека. В противном случае «b» больше и просто распечатайте результат.

Но кажется, что программа никогда не переходит на ярлык «больше». Как это можно исправить, пожалуйста? Спасибо.


person user1967718    schedule 17.12.2014    source источник
comment
courses.engr.illinois.edu/ ece390/books/artofasm/CH14/ Прочтите это: Generally, most programs test the condition code bits immediately after a comparison. Unfortunately, there are no conditional jump instructions that branch based on the FPU condition codes. Instead, you can use the fstsw instruction to copy the floating point status register ...   -  person Alex F    schedule 17.12.2014
comment
Да! Я думал, что есть такая инструкция, но я не мог вспомнить ее название. Но это только загружает регистр состояния fpu, например. AX (фств AX). Но как я могу загрузить содержимое AX в регистр FLAGS, чтобы я мог использовать инструкцию «jc»?   -  person user1967718    schedule 17.12.2014
comment
Прочитайте весь абзац.   -  person Alex F    schedule 17.12.2014


Ответы (2)


Математика FPU никогда не должна влиять на флаги CPU, такие как перенос и ноль!

Поэтому скопируйте флаги из FPU в регистр флагов CPU после инструкции fcomp, а затем проверьте флаги переноса и нуля, например:

fld qword ptr [a]
fcomp qword ptr [b]
wait                 ;wait FPU
fstsw ax             ;copy FPU flags to ax
sahf                 ;copy ax to CPU flags
jbe LessOrEqu        ;do less or equal
...
person GJ.    schedule 17.12.2014

Вот почему милые люди из Intel дали нам fcomi(p):

Выполняет неупорядоченное сравнение содержимого регистров ST(0) и ST(i) и по результатам устанавливает флаги состояния ZF, PF и CF в регистре EFLAGS.

Метод fstsw ax \ sahf является древним и даже не работает на всех «недревних» процессорах (некоторые старые процессоры x64 пропускают sahf). Использование wait является признаком действительно древнего кода, еще со времен, когда динозавры еще бродили по земле, а FPU был сопроцессором.

person harold    schedule 17.12.2014