【发布时间】:2016-07-21 18:02:33
【问题描述】:
这可能是个坏主意,但我想与内联汇编一起练习我的汇编。在我弄清楚如何读取命令行参数并使用它们创建文件here 之后,我将代码转换为 C++ 中的内联汇编。似乎一切都很好(没有编译警告或段错误),但程序绝对没有做任何事情。下面的代码和objdump。关于它为什么不执行语句的任何想法?
编辑:程序应该使用 argv1 中给出的文件名创建一个文件。
编辑 2:Intel(R) Core(TM) i7-4710HQ 64bit CPU @ 2.50GHz
编译完成:
g++ -o args args.cpp -g -nostartfiles
代码:
extern "C" void _start();
void _start(){
asm ( "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 %rsi;" /* Pop off stack */
"mov %rsi, %rdi;" /* Move argv[1] to rdi */
"mov $85, %rax;" /* #define __NR_creat 85 */
"mov $0x2E8, %rsi;" /* move 744 to rsi */
"syscall;"
"jmp exit;"
);
asm( "exit:\n\t"
"mov $60, %rax;"
"mov $1, %rdi;"
"syscall"
);
}
对象转储:
0000000000400292 <_start>:
400292: 55 push %rbp
400293: 48 89 e5 mov %rsp,%rbp
400296: 59 pop %rcx
400297: 48 83 f9 02 cmp $0x2,%rcx
40029b: 75 1a jne 4002b7 <exit>
40029d: 48 83 c4 08 add $0x8,%rsp
4002a1: 5e pop %rsi
4002a2: 48 89 f7 mov %rsi,%rdi
4002a5: 48 c7 c0 55 00 00 00 mov $0x55,%rax
4002ac: 48 c7 c6 e8 02 00 00 mov $0x2e8,%rsi
4002b3: 0f 05 syscall
4002b5: eb 00 jmp 4002b7 <exit>
【问题讨论】:
-
我强烈建议用 C++ 编写代码并告诉编译器打印代码的汇编语言。这将为您提供一个比较基准。
-
顺便说一句,汇编语言依赖于处理器。 ARM 处理器的汇编语言不同于 Intel 处理器的汇编语言。因此,当您谈论汇编语言时,请说明处理器。推论是汇编语言代码只能在目标处理器上工作并且不可移植。
-
请在您的问题中添加对汇编语言的目的或功能的描述。当没有参数传递给函数时,我很难理解为什么将寄存器与 2 进行比较。
-
@ThomasMatthews 更新了顶部的 cmets 和处理器。当程序启动时,命令行参数被压入堆栈。见图 3.9 - x86-64.org/documentation/abi.pdf
-
如果您想在 ASM 中编写整个函数,请将它们写入
.S文件中。您仍然可以在其上运行gcc进行组装和链接。 GNU C 内联 asm 不是为在 asm 中编写整个函数而设计的。 (尽管在 ARM 上,存在__attribute__((naked))以阻止编译器发出任何函数序言或ret指令。)另请参阅 the x86 tag wiki 和 this collection of links on how to use GNU inline asm correctly to avoid forcing the compiler to emit instructions it doesn't need。
标签: linux assembly g++ x86-64 inline-assembly