我正在阅读this,我注意到他们的示例显示fld将值加载到不同的位置(st0,st1,然后返回到st0),但没有指定加载到哪里。我假设fild的工作方式类似于它只是加载整数的方式(或者这是我的理解),但我可能错了。所以我的问题是: fld,更具体地说,fild将值加载到哪里?有没有一个参数来指定使用哪个fpu寄存器,或者它只是循环通过8,或者有一些我遗漏的完全不同的方式?
我特别使用的代码是尝试将3个数字相乘。我假设一种方法是加载到st0中,然后加载到st1中,然后加载到st2中,然后是fmul st0和st1 (结果是st0),然后是fmul st0和st2。代码如下:
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中的任何内容。新代码:
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内容:
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堆栈:
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
发布于 2018-01-09 07:47:44
您的原始代码是正确的。fld和fild将加载的值压入x87堆栈。该推送始终将值放入st0,将st0的旧值移至st1,将旧的st1移至st2,依此类推。
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中成功地运行了它。
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要组装和运行:
$ 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相乘。
https://stackoverflow.com/questions/28445271
复制相似问题