linux创建栈命令,linux - 从命令行创建文件 - 堆栈内存溢出

这不好。 您可能已经注意到,函数_start的编译器发出了函数序言push %rbp mov %rsp,%rbp :

400292: 55 push %rbp

400293: 48 89 e5 mov %rsp,%rbp

如果要执行此操作,请考虑至少使用-fomit-frame-pointer编译。 通过函数序言推动RBP ,当您弹出RCX时,您没有将命令行参数的数量放入RCX中 ,而是将RBP的值(现在位于堆栈的顶部)放入RCX中 。 当然,这会级联到其他使用错误值的堆栈操作。

您可以像这样直接编码_start函数,而不是忽略堆栈框架作为我的第一个建议:

asm ( ".global _start;" /* Make start symbol globally visible */

"_start:;"

"pop %rcx;" /* Contains argc */

"cmp $2, %rcx;" /* If argc = 2 (argv[0 & argv[1] exist) */

"jne exit;" /* If it's not 2, exit */

"add $8, %rsp;" /* Move stack pointer to argv[1] */

"pop %rdi;" /* Pop off stack */

"mov $85, %rax;" /* #define __NR_creat 85 */

"mov $0x2E8, %rsi;" /* move 744 to rsi */

"syscall;"

"exit:;"

"mov $60, %rax;" /* sys_exit */

"mov $2, %rdi;"

"syscall"

);

由于声明C ++函数的常规过程已被跳过,因此我们不必担心编译器会添加序言和结语代码。

您用于sys_creat的文件模式位不正确。 你有:

"mov $0x2E8, %rsi;" /* move 744 to rsi */

0x2E8 = 744十进制 我相信您的意图是将744八进制数放入%RSI中 。 八进制744是0x1e4。 为了使其更具可读性,您可以在GAS中使用八进制值,方法是在值前面加上0。这就是您要查找的内容:

"mov $0744, %rsi;" /* File mode octal 744 (rwxr--r--) */

而不是:

"pop %rsi;" /* Pop off stack */

"mov %rsi, %rdi;" /* Move argv[1] to rdi */

您可能直接跳入%rdi :

"pop %rdi;" /* Pop off stack */

您还可以将参数保留在堆栈上,并以这种方式直接访问它们:

asm ( ".global _start;" /* Make start symbol globally visible */

"_start:;"

"cmp $2, (%rsp);" /* If argc = 2 (argv[0 & argv[1] exist) */

"jne exit;" /* If it's not 2, exit */

"mov 16(%rsp), %rdi;" /* Get pointer to argv[1] */

"mov $85, %eax;" /* #define __NR_creat 85 */

"mov $0744, %esi;" /* File mode octal 744 (rwxr--r--) */

"syscall;"

"exit:;"

"mov $60, %eax;" /* sys_exit */

"mov $1, %edi;"

"syscall"

);

在最后一个代码片段中,在某些情况下,我还更改为使用32位寄存器。 您可以利用以下事实:在x86-64代码中,将值自动添加到32位寄存器中将使该值自动扩展为64位寄存器的高32位。 这样可以在指令编码上节省几个字节。

通过主要的w / 64位代码访问命令行参数

如果使用C / C ++运行时进行编译,则运行时将提供标签_start来执行程序启动,并修改OS传递的命令行参数以适合64位System V ABI 。 参数传递在3.2.3节中讨论。 特别是要以64位代码main的前两个参数是通过RDI和RSI传递的。 RDI将包含值argc , RSI将包含一个指向char *指针数组的指针。 由于这些参数不是通过堆栈传递的,因此我们不需要考虑任何函数序言和结语代码。

int main(int argc, char *argv[])

{

asm ( "cmp $2, %rdi;" /* If argc = 2 (argv[0 & argv[1] exist) */

"jne exit;" /* If it's not 2, exit */

/* _RSI_ (second arg to main) is a pointer

to an array of character pointers */

"mov 8(%rsi), %rdi;"/* Get pointer to second char * pointer in argv[] */

"mov $85, %eax;" /* #define __NR_creat 85 */

"mov $0744, %esi;" /* File mode octal 744 (rwxr--r--) */

"syscall;"

"exit:;"

"mov $60, %eax;" /* sys_exit */

"mov $1, %edi;"

"syscall"

);

}

您应该可以使用以下命令进行编译:

g++ -o testargs testargs.c -g

特别说明 :如果您打算最终将内联汇编与C / C ++代码一起使用,则必须了解GCC扩展汇编模板 ,约束,破坏等内容。这不在此问题的范围内。 如果您使用内联汇编,则与创建单独的汇编代码对象并从C / C ++调用它们相比,学习汇编程序要困难得多。 不正确地使用GCC的扩展内联组件非常容易。 代码乍一看似乎可以运行,但是随着程序变得越来越复杂,细微的错误可能会蔓延。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值