每个MOV指令都可以用PUSH/POP代替吗?

问题描述 投票:0回答:1

只是好奇是否可以在程序中将所有

MOV
替换为
PUSH/POP

我知道这种替代方法不切实际且效率低下。

这个 godbolt 示例展示了使用 MOV 的标准 printf 调用和另一个使用 PUSH/POP 的 printf 调用,以进行比较。我的直觉告诉我这是可能的,但一路上可能会遇到一些问题?

#include <stdio.h>

char format_string[] asm("format_string") = "%d %d %d %d %d\n";

void MOV_printf() {
    __asm__ (
        "subq $128, %%rsp\n\t"
        "lea format_string(%%rip), %%rdi\n\t"
        "movq $1, %%rsi\n\t"
        "movq $2, %%rdx\n\t"
        "movq $3, %%rcx\n\t"
        "movq $4, %%r8\n\t"
        "movq $5, %%r9\n\t"
        "call printf\n\t"
        "addq $136, %%rsp\n"
        ::: "rdi", "rsi", "rdx", "rcx", "r8", "r9", "rsp"
    );
}

void PUSH_POP_printf() {
    __asm__ (
        "subq $128, %%rsp\n\t"
        "lea format_string(%%rip), %%rdi\n\t"
        "pushq $1\n\t" 
        "popq %%rsi\n\t"
        "pushq $2\n\t" 
        "popq %%rdx\n\t"
        "pushq $3\n\t" 
        "popq %%rcx\n\t"
        "pushq $4\n\t" 
        "popq %%r8\n\t"
        "pushq $5\n\t" 
        "popq %%r9\n\t"
        "call printf\n\t"
        "addq $136, %%rsp\n"
        ::: "rdi", "rsi", "rdx", "rcx", "r8", "r9", "rsp"
    );        
}

int main() {
    MOV_printf();
    PUSH_POP_printf();
    return 0;
} 

解决方案

MOV r64, imm64
--- 替换为 4 个
pushw
和一个
popq
示例

MOV AH,DL
--- 可能的解决方法。 示例

陷阱

这些需要

mov

  • 控制寄存器(CR0、CR2、CR3、CR4 等...)
  • 调试寄存器(DR0、DR1、DR2 等...)
assembly gcc x86-64
1个回答
0
投票

mov %al,  (%rdi)
无法与
push
实现。任何加载/存储包含的单词或 qword 并将其存储回来的模拟都不是线程安全的;包含字的非原子 RMW 可以通过另一个线程存储到另一个字节。

如果您愿意接受这一点,那么也许部分重叠的

pop m16
操作可以用您在静态缓冲区中查找的值构造一个单词,您可以
pop m16
/
push m16
将其复制到原始字节。

但是您不知道

(%rdi)
处的字节是包含它的 16 位字的低字节还是高字节,因此您不知道可以访问
-1(%rdi)
0(%rdi)
中的哪一个,而无需进入下一页会出现段错误。只有“对齐”的 16 位加载/存储才能保证不会跨越任何更宽的边界(例如 4k 页),因此如果该字包含您知道有效的任何字节,则不会出现页错误。 (在 x86 和 x64 上读取同一页面内的缓冲区末尾是否安全? 单独使用

push

/

pop
无法检查
%rdi
的低位并进行相应的分支。
(x86-64 使得不可能有段限制,在 32 位模式下,段限制可能是奇数个字节,一般情况下不假设平面内存模型。但实际上,x86-64(仍然?)我认为 FS 和 GS 可能有奇数段基,所以 

mov %al, %fs:(%rdi)

更加未知;即使你可以

test %1, %dil
;
jnz
,仍然无法告诉你线性地址是奇数还是偶数。)

此外,除了调试和控制寄存器之外,x86-64 还删除了 FS/GS 以外的段寄存器的压入/弹出操作码。
https://www.felixcloutier.com/x86/push

。所以 mov ds, eax 也是不可模仿的。

    

© www.soinside.com 2019 - 2024. All rights reserved.