我正在尝试关注this和this教程进行学习。我遇到了一种奇怪的行为,我仍然不理解。
我有以下C代码:
void print(const char* str, char* vidptr, TerminalColor color){
for (unsigned i = 0; str[i] != '\0'; ++i){
unsigned int j = i*2;
vidptr[j] = str[i];
vidptr[j+1] = color;
}
return;
}
当我使用以下参数调用它时:
const char* str = "My string";
char* vidptr = (char*) 0xb8000;
print(str, vidptr, GREY); // GREY is equal to 7
在第一次执行body时,内存看起来像这样:
0xb8000: 0x07 0x00 0x00 0x00 0x00 0x00 0x00 0x00
我的预期:
0xb8000: 0x4D 0x07 0x00 0x00 0x00 0x00 0x00 0x00
使用连接到qemu-system-x86_64 gdbserver的gdb运行程序我发现在vidptr[j] = str[i];
一切正常运行之前,vidptr[j+1] = color;
的执行会覆盖第一个,就好像vidptr [j]相等到vidptr [j + 1]。
代码反汇编(如分区布局中的gdb所示)如下:
; vidptr[j] = str[i]
0x100144 <print+35> mov edx,DWORD PTR [rbp-0x8]
0x100147 <print+38> mov rax,QWORD PTR [rbp-0x18]
0x10014b <print+42> add rax,rdx
0x10014e <print+45> mov ecx,DWORD PTR [rbp-0x4]
0x100151 <print+48> mov rdx,QWORD PTR [rbp-0x20]
0x100155 <print+52> add rdx,rcx
0x100158 <print+55> movzx eax,BYTE PTR [rax]
0x10015b <print+58> mov BYTE PTR [rdx],al
; vidptr[j+1] = color
0x10015d <print+60> mov eax,DWORD PTR [rbp-0x4]
0x100160 <print+63> add eax,0x1
0x100163 <print+66> mov edx,eax ;eax = 0x1
0x100165 <print+68> mov rax,QWORD PTR [rbp-0x20] ;rax = 0xb8000
0x100169 <print+72> add rax,rdx ;here I observe the following: after I give the ni command to gdb the pc goes to the
;equivalent instruction `add eax,edx` but I oddly see the value of rax going to 0xb7fff.
;Then I send another ni command to gdb which shows again the instruction pointer to the
;next instruction (print+75).
0x10016c <print+75> mov edx,DWORD PTR [rbp-0x24] ; here the value of rax is again 0xb8000 instead of 0xb8001
0x10016f <print+78> mov BYTE PTR [rax],dl ; here the value written in the previous instruction is overwritten
0x100171 <print+80> add DWORD PTR [rbp-0x8],0x1
0x100175 <print+84> mov edx,DWORD PTR [rbp-0x8]
0x100178 <print+87> mov rax,QWORD PTR [rbp-0x18]
0x10017c <print+91> add rax,rdx
0x10017f <print+94> movzx eax,BYTE PTR [rax]
0x100182 <print+97> test al,al
0x100184 <print+99> jne 0x100139 <print+24>
有关为何发生这种情况的任何线索?
作为参考,遵循gdb的输出:
1: x/i $pc
=> 0x100166 <print+69>: add rax,rdx
2:x/8xb 0xb8000
0xb8000: 0x71 0x00 0x20 0x00 0x20 0x00 0x20 0x00
4: i = 0
5: j = 0
6: /x $rax = 0xb8000
(gdb) ni
1: x/i $pc
=> 0x100167 <print+70>: add eax,edx
2:x/8xb 0xb8000
0xb8000: 0x71 0x00 0x20 0x00 0x20 0x00 0x20 0x00
6: /x $rax = 0xb7fff
(gdb) p/x $eax
$3 = 0xb7fff
(gdb) p/x $edx
$4 = 0x1
(gdb) ni
1: x/i $pc
=> 0x100169 <print+72>: mov edx,DWORD PTR [rbp-0x24]
2:x/8xb 0xb8000
0xb8000: 0x71 0x00 0x20 0x00 0x20 0x00 0x20 0x00
6: /x $rax = 0xb8000
(gdb) ni
1: x/i $pc
=> 0x10016c <print+75>: mov BYTE PTR [rax],dl
2:x/8xb 0xb8000
0xb8000: 0x71 0x00 0x20 0x00 0x20 0x00 0x20 0x00
6: /x $rax = 0xb8000
(gdb) ni
1: x/i $pc
=> 0x10016e <print+77>: add DWORD PTR [rbp-0x8],0x1
2:x/8xb 0xb8000
0xb8000: 0x07 0x00 0x20 0x00 0x20 0x00 0x20 0x00
6: /x $rax = 0xb8000