初始化char []失败,esi包含错误的值

时间:2014-07-05 12:17:49

标签: c assembly x86

我想初始化一个char数组,但在我执行此操作时,我的程序崩溃了。这是我的代码:

void kernelEnteredMsg() {
    char str[] = "Kernel successfully entered!";
}

这是反汇编:

push ebp
mov ebp,esp
push edi
push esi
push ebx
sub esp,byte +0x30
lea edx,[ebp-0x2d]
mov ebx,0x402000 ; load an address outside my data segment
mov eax,0x1d
mov edi,edx
mov esi,ebx ; move this address to edi
mov ecx,eax
rep movsb ; here the programm crashes
add esp,byte +0x30
pop ebx
pop esi
pop edi
pop ebp
ret

我不明白为什么用0x402000加载esi。但这似乎导致错误。有人可以解释一下这里发生了什么,以及如何解决它?

PS:“内核成功输入!”在二进制文件中为0x1000。

C代码:

void kernelEnteredMsg();

void entryPoint() {
    kernelEnteredMsg();
}

void kernelEnteredMsg() {
    char str[] = "Kernel successfully entered!";
    int size = 28;
}

调用汇编代码:

extern _entryPoint
global _main
section .text
_main: ; start of kernel
nop
; setup ds, es, ss and gs
mov ax, 16
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0x4000
mov ax, 24
mov gs, ax
mov [gs:0], dword 0x07690748 ; test graphics
call _entryPoint ; enter kernel C code
jmp $ 

1 个答案:

答案 0 :(得分:3)

此代码将字符串从.text部分复制到本地堆栈,因为char数组不是“常量”。如果您不需要修改字符串,这可以提供一个简单的解决方案 - 只需将其设为const char。

  

我不明白为什么用0x402000加载esi。

ESI是字符串复制指令的来源' rep movsb',EDI是目的地。 地址由PE文件中的IMAGE_BASE + SECTION(IIRC)构成(假设它是PE)。 记住在文件中有一个FILE_ALIGN和一个SECTION_VIRTUAL_ADDRESS,所以一节可能是 在文件(FILE_ALIGN)中的位置0x1000和内存中的0x2000(VIRTUAL_ADDRESS)导致IMAGE_BASE + VIRTUAL_ADDRESS = 0x402000。

您可以使用像CFF Explorer(http://www.ntcore.com/exsuite.php)这样的PE资源管理器 显示这个(如果它是.bin文件,它可能是不适用的,但它必须有某种格式)

另一种可能是DF-Flag的错误状态导致字符串复制指令的错误行为(不应该发生,因为编译器应该处理这个)。

尝试插入

__asm__ ("cld");

在char str []之前或在__main过程中将字符串增量设置为' UP'。