eun*_*seo 1 assembly x86-64 gnu-assembler inline-assembly att
我正在研究基本的 shell 代码和orw代码。
但是,在此过程中,我收到以下错误消息:
错误:不支持的指令
mov
这是我的 C 和汇编代码框架:
// File name: orw.c
// Compile: gcc -o orw orw.c -masm=intel
__asm__(
".global run_sh\n"
"run_sh:\n"
"push 0x67\n"
"mov rax, 0x616c662f706d742f \n"
"push rax\n"
"mov rdi, rsp\n"
"xor rsi, rsi\n"
"xor rdx, rdx\n"
"xor eax, eax\n"
"mov eax, 2\n"
"syscall"
"\n"
"mov rdi, eax\n"
"mov rsi, rsp\n"
"sub rsi, 0x30\n"
"mov rdx, 0x30\n"
"xor eax, eax\n"
"syscall"
"\n"
"mov rdi,1\n"
"mov eax,1\n"
"syscall"
);
void run_sh();
int main() { run_sh(); }
Run Code Online (Sandbox Code Playgroud)
我已经放了movq,movl但它们没有用。
为什么我的代码会出现这个问题?
解决办法是什么?
用于gcc -save-temps将编译器输出保存到文件中,以便您可以将行号与实际的 asm 行相匹配。(或者将您的 asm 放入一个.s文件中以直接提供给as)。
这就是mov rdi, eax问题所在;问题在于操作数,而不是助记符。
有几种不同的形式mov(这也许就是为什么您会收到如此无用的错误消息1的原因),但是为两个操作数采用通用整数寄存器的形式需要它们的大小相同。
int fd = open(...)要将EAX零扩展为 RDI,请使用mov edi, eax. 有关零扩展指令的更多信息,
请参阅MOVZX 缺少 32 位寄存器到 64 位寄存器。
脚注 1:
GP 和段 regs、 mov到/从控制 regs、 mov到/从调试 regs以及类似的助记符movq xmm, xmm/mem需要mov通过 AT&T 语法q后缀消除歧义。请参阅AT&T 语法如何处理其他助记符和操作数大小后缀之间的歧义?
此外,您还可以优化 mov rsi, rsp;sub rsi, 0x30进入lea rsi, [rsp-0x30]。
是的,x86-64 SysV 有一个红色区域,因此在用户空间中使用低于 RSP 的最多 128 字节的空间是完全安全的,甚至syscall在 Linux 上也是如此。
如果不是这样,你会想要sub rsp, 0x30/ mov rsi, rsp。(但如果您最终想要这样做ret,则需要撤消该操作以将 RSP 指向返回地址。)