1

我正在尝试编写一个小程序,它采用两个硬编码字符指针并使用位于 .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 $espinswapMe的值与打印cd调用swapMe. 由于swapMe接受cd作为参数,我希望在调用时在堆栈上看到相同的值,swapMe但我没有。打印任何寄存器时我没有看到0xffffdb2c0x565556c0一次。请澄清我在调用函数、传入参数或打印寄存器中的值时做错了什么。我对 x86 很陌生,所以我可能在某个地方犯了一个菜鸟错误。

4

0 回答 0