我正在尝试编写一个小程序,它采用两个硬编码字符指针并使用位于 .S 文件中的外部 x86 32 位函数切换它们指向的内容。我正在使用基本的 gcc 编译器。这是我的 C 代码:
valSwap.c:
#include <stdio.h>
void extern swapMe(char* c, char* d);
int main() {
char* c = "boi";
char* d = "bra";
printf("%s, %s", c, d);
swapMe(c, d);
printf("%s, %s", c, d);
return 0;
}
在运行swapMe(c, d)
c 和 d 指向的字符串之前,已经很清楚了。运行后swapMe(c, d)
我得到一个Segmentation Fault
. 这是我的 swapMe 外部函数代码:
交换我.S:
.intel_syntax noprefix
.text
.global swapMe
swapMe:
push edi
push esi
mov eax, [esp+4]
mov ecx, [esp+8]
mov edi, [eax]
mov esi, [ecx]
mov [eax], esi
mov [ecx], edi
pop esi
pop edi
ret
现在由于 swapMe(c, d) 使用 cdecl 调用约定接收 2 个参数,我应该在堆栈中找到 c 和 d$esp+4
和$esp+8
。我试图打印这些值以确认它们是我所期望的。它们不是我所期望的,或者我试图错误地打印它们:
(gdb) p/s $esp+4
$1 = (void *) 0xffffdb08
(gdb) x/s $esp+4
0xffffdb08: ""
(gdb) p/s *($esp+4)
Attempt to dereference a generic pointer.
(gdb) x/s *($esp+4)
Attempt to dereference a generic pointer.
我还尝试将 $eax 打印为字符串,因为我将 $esp+4 的内容移动到 $eax 中。
(gdb) p/x $eax
$3 = 0xf7fa0000
(gdb) x/s $eax
0xf7fa0000: "\260=\033"
(gdb) x/s *$eax
0x1b3db0: <error: Cannot access memory at address 0x1b3db0>
(gdb) x/x $eax
0xf7fa0000: 0xb0
c
我还在输入之前打印了和d
之前的十六进制值,swapMe
看看我是否至少得到了正确的值:
(gdb) p &c
$12 = (char **) 0xffffdb2c
(gdb) p c
$16 = 0x565556c0 "boi"
(gdb) p &d
$14 = (char **) 0xffffdb28
(gdb) p d
$15 = 0x565556c4 "bra"
我还打印了一些其他可能相关的值:
30x56555621 <swapMe+2> mov eax,DWORD PTR [esp+0x4] 3
30x56555625 <swapMe+6> mov ecx,DWORD PTR [esp+0x8] 3
>30x56555629 <swapMe+10> mov edi,DWORD PTR [eax] 3
30x5655562b <swapMe+12> mov esi,DWORD PTR [ecx]
(gdb) p/x $eax
$8 = 0xf7fa0000
0x56555621 <swapMe+2> mov eax,DWORD PTR [esp+0x4] 3
30x56555625 <swapMe+6> mov ecx,DWORD PTR [esp+0x8] 3
30x56555629 <swapMe+10> mov edi,DWORD PTR [eax] 3
>30x5655562b <swapMe+12> mov esi,DWORD PTR [ecx] 3
30x5655562d <swapMe+14> mov DWORD PTR [eax],esi 3
30x5655562f <swapMe+16> mov DWORD PTR [ecx],edi
p/x $edi
$11 = 0x1b3db0
30x56555621 <swapMe+2> mov eax,DWORD PTR [esp+0x4] 3
30x56555625 <swapMe+6> mov ecx,DWORD PTR [esp+0x8] 3
30x56555629 <swapMe+10> mov edi,DWORD PTR [eax] 3
30x5655562b <swapMe+12> mov esi,DWORD PTR [ecx] 3
>30x5655562d <swapMe+14> mov DWORD PTR [eax],esi 3
30x5655562f <swapMe+16> mov DWORD PTR [ecx],edi
(gdb) p/x $ecx
$19 = 0x565555f5
(gdb) p/x $esi
$20 = 0x8310c483
我不明白为什么当我打印$eax, $edi, $ecx, and $esp
inswapMe
的值与打印c
与d
调用swapMe
. 由于swapMe
接受c
并d
作为参数,我希望在调用时在堆栈上看到相同的值,swapMe
但我没有。打印任何寄存器时我没有看到0xffffdb2c
或0x565556c0
一次。请澄清我在调用函数、传入参数或打印寄存器中的值时做错了什么。我对 x86 很陌生,所以我可能在某个地方犯了一个菜鸟错误。