gpt4 book ai didi

c - 如何读取 _start 函数中的参数?

转载 作者:太空狗 更新时间:2023-10-29 11:18:01 26 4
gpt4 key购买 nike

我正在 64 位 Linux 中构建没有 glibc 的简单应用程序。但我不知道如何获取参数。

我用谷歌搜索,发现 RDI 是 argc,RSI 是 argv。但它没有用。

当 _start 函数开始使用 gdb 时,我看到了寄存器,但 RDI 和 RSI 都是 0x0。我还测试了最简单的 assembly 应用程序,但结果是一样的。 RDI 和 RSI 为 0x0。我相信 argc 不应该是 0x0,即使我没有向程序传递任何参数也是如此。

_start:
jmp $

这是我尝试过的 C 代码:

//Print Hello world WITHOUT standard library
//ONLY WITH SYSTEM CALL

#define ReadRdi(To) asm("movq %%rdi,%0" : "=r"(To));
#define ReadRsi(To) asm("movq %%rsi,%0" : "=r"(To));

void __Print(const char *str);
void __Exit();

void Test(const char *a){
long aL;
ReadRdi(aL);
char *aC = (int) aL;
__Print("Test argument: ");
__Print(aC);
__Print("\n");
}

void _start() {
long argcL;
long argvL;
ReadRdi(argcL);
ReadRsi(argvL);
int argc = (int) argcL;
char **argv = (char **) argvL;
__Print("Arguments: ");
for(int i = 0; i < argc; i ++) {
__Print(argv[i]);
__Print(", ");
}
__Print("\n");
Test("Hello, world!");
__Exit();
}

结果是:

Arguments:
Test argument: Hello, world!

我用gdb检查了堆栈(RBP~RSP中的内存值),但似乎什么都没有。

我试着改变

void _start() {
long argcL;
long argvL;
ReadRdi(argcL);
ReadRsi(argvL);
int argc = (int) argcL;
char **argv = (char **) argvL;
__Print("Arguments: ");

void _start(int argc, char **argv) {
__Print("Arguments: ");

但我仍然看不到任何参数输出。

__Print打印消息(使用sys_write系统调用),__Exit退出程序(使用sys_exit系统调用)。

打印.asm:

section     .text
global __Print
__Print:
mov rdx, 0
push rdi
jmp .count
.count:
add rdx, 1
add rdi, 1
cmp byte[rdi], 0
jne .count
.print:
pop rdi
mov rcx, rdi ;message to write
mov rbx, 1 ;file descriptor (stdout)
mov rax, 4 ;system call number (sys_write)
int 0x80 ;call kernel
ret

退出.asm:

section     .text
global __Exit
__Exit:
mov rax,1 ;system call number (sys_exit)
int 0x80

添加:我用这个命令链接:

gcc -o sysHello Exit.o Print.o sysHello.o -nostdlib -nodefaultlibs -g

最佳答案

最简单的方法是在 asm 中编写 _start,并让它使用标准调用约定调用您的 C 函数。

参见 wiki 获取 ABI 文档的链接,该文档描述了在流程启动时在哪里可以找到所有内容。 (或使用 Ian 评论中的链接)。

_start 编写为 C 函数需要内联汇编,因为没有标准方法告诉编译器 argc 是返回地址通常所在的位置。因此,直接用 asm 编写它并在将 args 放入寄存器以实现正常调用约定后让它调用 main 会更容易。

我用 perf 计数器测试事物的 asm 程序片段:

cmp dword [rsp], 2
jg addrmode_lat_3comp ; argc > 2 ; $(seq 2)
jge addrmode_lat_1comp ; argc >= 2 ; $(seq 1)
jmp loadlat_1comp ; argc < 2 ; $(seq 0)

通过测试 argc,它会跳转到三个循环之一,具体取决于我是使用 2、1 还是不使用 args 运行它。它使用 NASM 语法。

关于c - 如何读取 _start 函数中的参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35337196/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com