diff --git a/src/advance/unsafe/inline-asm.md b/src/advance/unsafe/inline-asm.md index 12ee253d75..c6c4cbab34 100644 --- a/src/advance/unsafe/inline-asm.md +++ b/src/advance/unsafe/inline-asm.md @@ -195,7 +195,7 @@ fn mul(a: u64, b: u64) -> u128 { ## Clobbered 寄存器 -在很多情况下,无需作为输出的状态都会被内联汇编修改,这个状态被称之为 "clobbered"。 +在很多情况下,无需作为输出的寄存器的状态都会被内联汇编修改,这个状态被称之为 "clobbered"。 我们需要告诉编译器相关的情况,因为编译器需要在内联汇编语句块的附近存储和恢复这种状态。 @@ -241,7 +241,7 @@ fn main() { 即使 `eax` 从没有被读取,我们依然需要告知编译器这个寄存器被修改过,这样编译器就可以在执行汇编之前存储寄存器中的值。这个需要通过将输出声明为 `_` 而不是一个具体的变量名,代表着该输出值被丢弃。 -这段代码也会绕过一个限制: `ebx` 是一个 LLVM 保留寄存器,意味着 LLVM 会假设它拥有寄存器的全部控制权,并在汇编代码块结束时将寄存器的状态恢复到最开始的状态。由于这个限制,该寄存器无法被用于输入或者输出,除非编译器使用该寄存器的满足一个通用寄存器的需求(例如 `in(reg)` )。 但这样使用后, `reg` 操作数就在使用保留寄存器时变得危险起来,原因是我们可能会无意识的破坏输入或者输出,毕竟它们共享同一个寄存器。 +这段代码也会绕过一个限制: `ebx` 是一个 LLVM 保留寄存器,意味着 LLVM 会假设它自己拥有该寄存器的全部控制权,并在汇编代码块结束时将寄存器的状态恢复到最开始的状态。由于这个限制,该寄存器无法被用于输入或者输出,除非编译器在分配通用寄存器时恰好选择了它(例如 `in(reg)` )。 但这样使用后, `reg` 操作数就在使用保留寄存器时变得危险起来,原因是我们可能会无意识的破坏输入或者输出,毕竟它们共享同一个寄存器。 为了解决这个问题,我们使用 `rdi` 来存储指向输出数组的指针,通过 `push` 的方式存储 `ebx`:在汇编代码块的内部读取 `ebx` 的值,然后写入到输出数组。后面再可以通过 `pop` 的方式来回复 `ebx` 到初始的状态。