首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >NASM x87文件指令

NASM x87文件指令
EN

Stack Overflow用户
提问于 2015-02-11 09:52:22
回答 1查看 2.3K关注 0票数 0

我正在阅读this,我注意到他们的示例显示fld将值加载到不同的位置(st0,st1,然后返回到st0),但没有指定加载到哪里。我假设fild的工作方式类似于它只是加载整数的方式(或者这是我的理解),但我可能错了。所以我的问题是: fld,更具体地说,fild将值加载到哪里?有没有一个参数来指定使用哪个fpu寄存器,或者它只是循环通过8,或者有一些我遗漏的完全不同的方式?

我特别使用的代码是尝试将3个数字相乘。我假设一种方法是加载到st0中,然后加载到st1中,然后加载到st2中,然后是fmul st0和st1 (结果是st0),然后是fmul st0和st2。代码如下:

代码语言:javascript
复制
mov dword [ebp-8], 4
mov dword [ebp-12], ecx
fild dword [ebp-4]
fild dword [ebp-8]
fild dword [ebp-12]
fmul st0, st1
fmul st0, st2
fistp dword [ebp-8]
mov eax, dword [ebp-8]

ecx =5和ebp-4 =5

这段代码崩溃了,使用OllyDbg我发现在00000069处有访问冲突,但目前没有包含在任何寄存器中。

那么,有没有一种方法可以指定fild加载值的位置,有没有一种很好的方法来找出它们应该放在哪里,如果我在循环中运行它,这会改变什么吗?

--编辑3--基本上是固定的,有点。一件很重要的事情是,fmul不会将值推送到st0,它只是覆盖st0中的任何内容。新代码:

代码语言:javascript
复制
mov dword [ebp-8], ecx
fild dword [ebp-4]
fild dword [four]
fild dword [ebp-8]
fmul st1
fmul st2
fistp dword [ebp-12]
mov eax, dword [ebp-12]

这会循环并递减,直到ecx == 2,然后尝试fild 2和1会得到与前面相同的bad -NAN FFFF C0000000 00000000。我不确定3与2或1有什么不同(除了更小),但这就是它开始给出不好的值的时候。我应该注意到抛出了ERROR_MOD_NOT_FOUND,尽管我不太确定这是什么意思,因为所有的cpu和fpu寄存器都应该是可访问的。

--编辑2--修复了Parham Alvani使用文档显示的pop内容:

代码语言:javascript
复制
mov dword [ebp-8], ecx      ; moves eax (starts as 5) into local var (fild can't take a cpu register)
fild dword [ebp-4]          ; starts as 5, moves down with outer loop
fild dword [four]           ; the integer 4
fild dword [ebp-8]          ; starts as 5, moves down with inner loop
fmul st0, st1               ; 0 := 0 * i
fmul st0, st3
fistp dword [ebp-12]        ; move st0 to local var
mov eax, dword [ebp-12]     ; move local var to eax

这会将puts设置为5,然后将bad -NAN FFFF C0000000 00000000设置为两次。fmul似乎没有做任何事情(可能是因为值不好)。有没有更好的加载值的方法?看起来我对fild做错了什么,但根据第一个链接中提供的例子,正如定义的here一样,fild只是将您提供的任何东西推送到st0上。

--EDIT 1--正如Jester建议的那样,我现在每次循环都会弹出fpu堆栈:

代码语言:javascript
复制
mov dword [ebp-8], 4
mov dword [ebp-12], ecx
fild dword [ebp-4]
fild dword [ebp-8]
fild dword [ebp-12]
fmul st0, st1
fmul st0, st2
fstp st2
fstp st1
fistp dword [ebp-8]
mov eax, dword [ebp-8]

这段代码仍然会崩溃。00000009处的访问冲突,st0-4是0,st5 = 100,st6 = 4,st7 =4

EN

回答 1

Stack Overflow用户

发布于 2018-01-09 07:47:44

您的原始代码是正确的。fldfild将加载的值压入x87堆栈。该推送始终将值放入st0,将st0的旧值移至st1,将旧的st1移至st2,依此类推。

代码语言:javascript
复制
fild dword [ebp-4]   ; st0 = x
fild dword [ebp-8]   ; st1 = x, st2 = y
fild dword [ebp-12]  ; st2 = x, st1 = y, st0 = z
fmul st0, st1        ; st2 = x, st1 = y, st0 = z * y
fmul st0, st2        ; st2 = x, st1 = y, st0 = z * y * x
fistp dword [ebp-8]  ; st1 = x, st0 = y

您的代码可能会崩溃,因为ebp指向错误的位置,或者因为代码的另一部分存在错误,而不是您发布的部分。你不会说哪条指令崩溃了。在崩溃时刻,程序计数器(pc)指向崩溃指令。

我将您的代码放在一个简短的程序中,并在我的OpenBSD/amd64机器上的gdb中成功地运行了它。

代码语言:javascript
复制
section .data
    dd 0
    dd 0
    dd 5
space:

section .text
global main
main:
    mov ebp, space
    mov ecx, 5
    mov dword [ebp-8], 4
    mov dword [ebp-12], ecx
    fild dword [ebp-4]
    fild dword [ebp-8]
    fild dword [ebp-12]
    fmul st0, st1
    fmul st0, st2
    fistp dword [ebp-8]
    mov eax, dword [ebp-8]
    int 3

要组装和运行:

代码语言:javascript
复制
$ nasm -felf64 fmul3.s && gcc -nopie -o fmul3 fmul3.o 
$ gdb fmul3
...
(gdb) run
...
Program received signal SIGTRAP, Trace/breakpoint trap.
...
(gdb) x/3wd (char *)&space - 12
0x601000 <__data_start>:        5       100     5
(gdb) print (int)$rax
$1 = 100

程序成功地将5*4*5= 100相乘。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28445271

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档