解决内联汇编64位Linux系统调用提示Bad Address

在参考《Linux 下系统调用的三种方法》这篇文章的时候,前面的syscall()和chmod()两种方法完成系统调用chmod都可以正常执行。

但当我使用内联汇编时,程序执行提示errno=14 Bad Address

asm ( 汇编程序模板
: 输出操作数 可选的
: 输入操作数 可选的
: 修饰寄存器列表 可选的
)

//关键代码
    asm(
        "int $0x80" //immediate value start with $ in at&t syntax
        : "=a"(rc) //output operand,'=' means write only,'a' means use eax
        : "0"(SYS_chmod), "b"(file_name), "c"(mode) //'0' use the same register as output operand 1(eax here)
        );

而这段代码,根据作者所述在32位Linux执行和前两种结果一致,那么应该就是64位系统调用的问题,经过一番搜索,找到了答案:在64位Linux上使用中断0x80

64位系统调用的指令是syscall,调用的寄存器也不同于32位的eax ebx ecx…而是rax rdi rsi…

相应的寄存器约束:

r:I/O,表示使用一个通用寄存器,由GCC在%rax/%eax/%ax/%al、%rbx/%ebx/%bx/%bl、%rcx/%ecx/%cx/%cl、%rdx/%edx/%dx/%dl中选取一个GCC认为是合适的;
q:I/O,表示使用一个通用寄存器,与r的意义相同;
g:I/O,表示使用寄存器或内存地址;
m:I/O,表示使用内存地址;
a:I/O,表示使用%rax/%eax/%ax/%al;
b:I/O,表示使用%rbx/%ebx/%bx/%bl;
c:I/O,表示使用%rcx/%ecx/%cx/%cl;
d:I/O,表示使用%rdx/%edx/%dx/%dl;
D:I/O,表示使用%rdi/%edi/%di;
S:I/O,表示使用%rsi/%esi/%si;
f:I/O,表示使用浮点寄存器;
t:I/O,表示使用第一个浮点寄存器;
u:I/O,表示使用第二个浮点寄存器;
A:I/O,表示把%eax与%edx组合成一个64位的整数值;
o:I/O,表示使用一个内存位置的偏移量;
V:I/O,表示仅仅使用一个直接内存位置;
i:I/O,表示使用一个整数类型的立即数;
n:I/O,表示使用一个带有已知整数值的立即数;
F:I/O,表示使用一个浮点类型的立即数;

修改后:

asm(
    "syscall" //immediate value start with $ in at&t syntax
    : "=a"(rc) //output operand,'=' means write only,'a' means use eax
    : "0"(SYS_chmod), "D"(file_name), "S"(mode) //'0' use the same register as output operand 1(eax here)
    );

正常提示Operation not permitted

参考:
Linux 下系统调用的三种方法
系统调用约定
在64位Linux上使用中断0x80
内联汇编
如果您在 64 位代码中使用 32 位国际0x80 Linux ABI,会发生什么情况?

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值