为什么我不能在英特尔x86-64汇编中直接将一个字节从内存移到64位寄存器?
例如,此代码:
extern printf
global main
segment .text
main:
enter 2, 0
mov byte [rbp - 1], 'A'
mov byte [rbp - 2], 'B'
mov r12, [rbp - 1]
mov r13, [rbp - 2]
xor rax, rax
mov rdi, Format
mov rsi, r12
mov rdx, r13
call printf
leave
ret
segment .data
Format: db "%d %d", 10, 0
印刷品:
65 16706
为了使代码正常工作,我需要将寄存器r12和r13的移动字节更改为:
xor rax, rax
mov al, byte [rbp - 1]
mov r12, rax
xor rax, rax
mov al, byte [rbp - 2]
mov r13, rax
现在,它打印出预期内容:
65 66
我们为什么要这样做?
有更简单的方法吗?
谢谢
可以使用movzx指令将字节移动到64位寄存器。
对你来说,那就是
movzx r12, byte ptr [rbp - 1]
movzx r13, byte ptr [rbp - 2]
另一种避免按时间寻址内存的方法是
mov ax, word ptr [rbp - 2]
movzx r12, al
movzx r13, ah
但最后一条指令不会被编译。看见http://www.felixcloutier.com/x86/MOVZX.html“在64位模式下,如果使用REX前缀,则无法对r/m8进行编码以访问以下字节寄存器:AH、BH、CH、DH。”
所以我们要做到以下几点:
mov ax, word ptr [rbp - 2]
movzx r12, al
mov al, ah
movzx r13, al
但是,像第一个示例中那样的两个movxz'e可能更快(处理器可能会优化内存访问)-速度取决于更大的上下文,应该在复杂的环境中进行测试。
您可以利用这样一个事实,即在64位模式下,修改32位寄存器也会清除最高位(63-32),但无论如何,您无法使用movzx指令在64位下对ah
寄存器进行编码,即使是在64位模式下出现的新寄存器的32位部分(movzx r13d,ah
也无法工作)。
您可以按以下方式使用64位rNN寄存器的8位、16位和32部分:
rNNb-字节rNNw-字rNNd-dword
例如,r10b、r10w、r10d。下面是代码中的示例
xor r8d,dword ptr [r9+r10*4]
.....
xor r8b, al
.....
xor eax, r11d
请注意:rNN寄存器的'h'部分不可用,它们仅适用于四个第一寄存器:ah、bh、ch和dh。
另一个注意事项:修改64位寄存器的32位部分时,较高的32位会自动设置为零。
使用寄存器的最快方法是始终清除最高位,以消除对寄存器先前内容的错误依赖。这是英特尔推荐的方法,将允许更好的无序执行(OOE)和寄存器重命名(RR)。除此之外,在现代处理器上使用完整寄存器而不是使用它们的较低部分更快:骑士登陆和炮弹湖。所以这是在这些处理器上运行更快的代码(它将使用OOE和RR):
movzx rax, word ptr [rbp - 2]
movzx r12, al
shr rax, 8
mov r13, rax
关于Knights Landing和未来主流处理器(如CannonLake),英特尔明确表示,8位和16位寄存器上的指令将比CannonLake上32位或64位寄存器上的指令慢得多,因此它们现在正在Knights Landing上。
如果您在编写时考虑到OOB和RR,那么您的汇编代码将更快。
酌情使用带零或符号扩展名的移动。
movsx-rax,字节[rbp-1]符号扩展到rax。
我可以使用MOV指令将存储在内存中的数据项移动到我选择的通用寄存器中。 现在,不要向我开枪,但以下是如何实现的:
问题内容: 我试图将ArrayList添加到Jlist,但我给出的唯一理解是编写这样的代码: 让我感到困惑的是,为什么我不能像这样直接将ArrayList直接添加到Jlist中: 提前致谢。 问题答案: 包含“ helper”构造函数的目的是使使用简单数据结构更加容易。 的(和许多Swing组件)实际上是指与提供实际数据视图模型中使用。 原始设计可以追溯到将Swing纳入主库之前(在JDK 1.3
问题内容: 我试图将ArrayList添加到Jlist,但我给出的唯一理解是编写这样的代码: 让我感到困惑的是,为什么我不能像这样直接将ArrayList直接添加到Jlist中: 提前致谢。 问题答案: 包含“ helper”构造函数的目的是使使用简单数据结构更加容易。 的(和许多Swing组件)实际上是指与提供实际数据视图模型中使用。 原始设计可以追溯到将Swing纳入主库之前(在JDK 1.3
基本上指令有8->16、8->32、8->64、16->32和16->64。 32->64的转换在哪里?我必须使用签名版本吗? 如果是的话,您如何使用完整的64位来表示无符号整数?
如果一个表达式包含任何整数大小或更小的内容,其结果总是整数,即使两个字节之和适合一个字节。 为什么我们在一个字节中添加最后两个字节时会发生这种情况?没有编译器错误。
根据Android指南,http://developer.android.com/training/basics/fragments/communicating.html一个片段应该通过宿主Activity向另一个片段发送数据。我想知道这有什么原因。因为在我的代码中,我放置了一个变量来保存指向另一个片段的指针,并在onActivityCreated中赋值 后来,如果我想为FragmentType2