这就是我通过阅读一些内存分段文档所理解的:当调用一个函数时,有一些指令(称为函数序言)将帧指针保存在堆栈上,将堆栈指针的值复制到基本指针中并保存一些局部变量的内存.
这是我尝试使用GDB调试的一个简单代码:
void test_function(int a, int b, int c, int d) {
int flag;
char buffer[10];
flag = 31337;
buffer[0] = 'A';
}
int main() {
test_function(1, 2, 3, 4);
}
Run Code Online (Sandbox Code Playgroud)
调试此代码的目的是了解调用函数时堆栈中发生的情况:因此我必须在执行程序的各个步骤(在调用函数之前和执行期间)检查内存.虽然我设法通过检查基指针来查看返回地址和保存的帧指针之类的东西,但我真的无法理解在反汇编代码之后我要写的内容.
拆解:
(gdb) disassemble main
Dump of assembler code for function main:
0x0000000000400509 <+0>: push rbp
0x000000000040050a <+1>: mov rbp,rsp
0x000000000040050d <+4>: mov ecx,0x4
0x0000000000400512 <+9>: mov edx,0x3
0x0000000000400517 <+14>: mov esi,0x2
0x000000000040051c <+19>: mov edi,0x1
0x0000000000400521 <+24>: call 0x4004ec <test_function>
0x0000000000400526 <+29>: pop rbp
0x0000000000400527 <+30>: ret
End …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用文件描述符.我已经被教导使用文件流(fopen,fread等),但现在我想了解这种使用文件的其他方式.
我要发布的这段代码有点琐碎和愚蠢:它只是打开一个名为"file"的文件,它具有以下结构:4个字符,一个整数和每行的'\n'值.我并没有尝试做任何有用的事情,我只是尝试做一些基本的操作,我曾经非常轻松地使用流.特别是,我的文件有这个信息:
row 1
row 2
row 3
Run Code Online (Sandbox Code Playgroud)
"row"和空格代表4个字符,数字代表整数.我只想打印文件内容,但是我想记住我遇到的int值(否则打印每个符合的字符就足够了)(因此我可以根据该值进行一些详细说明,如果我想要的话)至).这是我使用的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
int main() {
int fd;
fd = open("file", O_RDONLY);
char *buffer;
buffer = (char*)malloc(20*sizeof(char));
unsigned char x;
int y = -1;
int number = 1;
int i=0, j;
while(read(fd, &x, 1*sizeof(char)) > 0) {
for(j=0; j<3; j++) {
buffer[i] = x;
i++;
read(fd, &x, sizeof(char)); // or 1 instead of sizeof(char)
}
buffer[i] = x;
buffer[i+1] = '\0';
printf("byte read: %d\n", …Run Code Online (Sandbox Code Playgroud) 我目前正在通过反汇编C程序并试图了解它们的作用来进行汇编阅读.
我被困在一个简单的问题:一个简单的你好世界计划.
#include <stdio.h>
#include <stdlib.h>
int main() {
printf("Hello, world!");
return(0);
}
Run Code Online (Sandbox Code Playgroud)
当我拆卸主要时:
(gdb) disassemble main
Dump of assembler code for function main:
0x0000000000400526 <+0>: push rbp
0x0000000000400527 <+1>: mov rbp,rsp
0x000000000040052a <+4>: mov edi,0x4005c4
0x000000000040052f <+9>: mov eax,0x0
0x0000000000400534 <+14>: call 0x400400 <printf@plt>
0x0000000000400539 <+19>: mov eax,0x0
0x000000000040053e <+24>: pop rbp
0x000000000040053f <+25>: ret
Run Code Online (Sandbox Code Playgroud)
我理解前两行:基本指针保存在堆栈上(通过push rbp,这会导致堆栈指针的值减少8,因为它已经"增长")并且堆栈指针的值被保存在基指针中(这样,参数和局部变量可以分别通过正偏移和负偏移轻松到达,而堆栈可以保持"增长").
第三行提出了第一个问题:为什么0x4005c4("Hello,World!"字符串的地址)在edi寄存器中移动而不是在堆栈中移动?printf函数不应该将该字符串的地址作为参数吗?据我所知,函数从堆栈中获取参数(但在这里,看起来参数放在该寄存器中:edi)
在StackOverflow上的另一篇文章中,我读到"printf @ ptl"就像一个调用真正的printf函数的存根函数.我试图反汇编这个功能,但它变得更加混乱:
(gdb) disassemble printf
Dump of assembler code for function __printf:
0x00007ffff7a637b0 <+0>: sub rsp,0xd8
0x00007ffff7a637b7 <+7>: test al,al …Run Code Online (Sandbox Code Playgroud)