如何将 eax 寄存器中的值,ah 和 al 左移 2 个字节? x86 汇编
How to mov values in eax register, ah and al left by 2 bytes? x86 Assembly
我有一个关于如何在 x86 汇编 eax 寄存器中移动值的问题。我知道 32 位寄存器分解为更小的组件寄存器,低 16 位为 ax,16 位进一步分解为 8 位寄存器 ah 和 al。
我目前正在为 x86 汇编语言作业编写一个程序,该程序希望我仅使用 mov、add 和 sub 命令在寄存器中移动四个 8 位十六进制值。该程序首先让您通过加减变量来移动变量值,这没问题。
第二部分(phase2)是将每个值放入每个eax 8位位置。但是,我知道您只能访问较低的两个 8 位位置(“ah”和“al”。)我需要以某种方式将 ah 和 al 一起移动到 eax 的前导 16 位,将添加的值推送到 ah 和al 留下两个字节的位置? (问号,因为我不知道。)我相当确定我可以将正确的值添加回 ah 和 al 以完成解决方案。
我相信这样做的方法是将 'some hex value' 添加到 ah 并保留溢出,但我似乎无法理解它的逻辑。 “从逻辑上讲,”我想说这似乎是最好的行动方案,但我不确定如何实施。而且,由于我不能全神贯注,我找不到我应该找到的隐藏算法。 Phase2 应该只有 aprx 21 行,所以我知道它不是大量的添加指令列。
任何关于如何思考这个问题的指导都将不胜感激。感谢任何人。
.386
.model flat,stdcall
.stack 4096
ExitProcess proto,dwExitCode:dword
.data
var1 BYTE 'A'
var2 BYTE 'B'
var3 BYTE 'C'
var4 BYTE 'D'
.code
main proc
;phase1
mov al, var1; store 'A'
mov ah, var4; store 'D'
mov var1, ah; move 'D' to var1
sub ah, 1; make ah 'C'
mov var4, ah; move 'C' to var4
sub ah, 1; make ah 'B'
mov var3, ah; move 'B' to var3
mov var2, al; 'mov al to var2
;var1 BYTE 'D'
;var2 BYTE 'A'
;var3 BYTE 'B'
;var4 BYTE 'C'
;phase2
mov ah, var1; store 'D'
mov al, var2; store 'A'
; this is where I want to shift al and ah left two bytes
; once the first two bytes of eax equal 'DA' move 'B' 'C'
; into ah and al
mov ah, var3; store 'B'
mov al, var4; store 'C'
;eax should read 'DABC' = 44414243
invoke ExitProcess,0
main endp
end main
如果您不能像正常人一样使用shl eax, 16
,您的其他选择包括:
add eax,eax
重复 16 次(糟糕,慢),循环部分展开或完全展开。
- 以偏移量存储/重新加载:也很慢,但仅用于延迟(存储转发停顿)。吞吐量还可以,而延迟非常接近与典型现代 x86 上的 16x
add
方式相同的 16 个周期。
sub esp, 16 ; reserve some stack space.
...
mov [esp+2], ax ; 2 byte store
mov eax, [esp] ; 4-byte reload with previous AX in the top half
mov ah, ... ; overwrite whatever garbage in the low 2 bytes
mov al, ...
x86 是小端 ,因此 load/store 的 EAX 到 addr
loads/stores AL 到相同的 addr
,和 AH 到 addr+1
.,高 2 个字节来自 addr+2 和 +3.
在写入 AH 和 AL 后读取 EAX 也会强制 CPU 合并部分寄存器,如果它从完整的 EAX 中分离重命名 AH(可能还有 AL),但很明显,如果你只限制自己ISA 的一小部分然后高性能不是您的首要目标。 (有关详细信息,请参阅 and 。)
store-forwarding stall部分见Can modern x86 implementations store-forward from more than one prior store?
取决于你对新的低部分(新的 AH 和 AL)做了多少,你实际上可以在一个单独的寄存器(比如 DH 和 DL)中做它们,所以无序的 exec 可以得到开始了这项工作,没有对存储转发重新加载的错误依赖,尤其是在 CPUs 上,它们没有从 EAX 中单独重命名 AL(甚至 AH)。 (即 CPU 不是 Intel P6 系列的,例如顽皮的老 Nehalem)。
所以你会这样做
mov [esp+2], ax ; 2 byte store
mov eax, [esp] ; 4-byte reload with previous AX in the top half
mov dl, ...
mov dh, ...
... more computation with these two
mov ax, dx ; replace low 2 bytes of EAX
mov ax,dx
可能需要等待旧的 EAX 值“准备好”,即重新加载完成,因此它可以作为 运行 该指令的一部分合并到其中。 (在 Intel Sandybridge 系列和所有非 Intel CPUs 上。)所以这让 DL/DH 上的计算与存储转发延迟重叠。
明确一点,所有这些关于权衡的讨论都是关于性能,而不是正确性;我在这里展示的所有方法都是完全正确的。(除非我弄错了 :P)
我有一个关于如何在 x86 汇编 eax 寄存器中移动值的问题。我知道 32 位寄存器分解为更小的组件寄存器,低 16 位为 ax,16 位进一步分解为 8 位寄存器 ah 和 al。
我目前正在为 x86 汇编语言作业编写一个程序,该程序希望我仅使用 mov、add 和 sub 命令在寄存器中移动四个 8 位十六进制值。该程序首先让您通过加减变量来移动变量值,这没问题。
第二部分(phase2)是将每个值放入每个eax 8位位置。但是,我知道您只能访问较低的两个 8 位位置(“ah”和“al”。)我需要以某种方式将 ah 和 al 一起移动到 eax 的前导 16 位,将添加的值推送到 ah 和al 留下两个字节的位置? (问号,因为我不知道。)我相当确定我可以将正确的值添加回 ah 和 al 以完成解决方案。
我相信这样做的方法是将 'some hex value' 添加到 ah 并保留溢出,但我似乎无法理解它的逻辑。 “从逻辑上讲,”我想说这似乎是最好的行动方案,但我不确定如何实施。而且,由于我不能全神贯注,我找不到我应该找到的隐藏算法。 Phase2 应该只有 aprx 21 行,所以我知道它不是大量的添加指令列。
任何关于如何思考这个问题的指导都将不胜感激。感谢任何人。
.386
.model flat,stdcall
.stack 4096
ExitProcess proto,dwExitCode:dword
.data
var1 BYTE 'A'
var2 BYTE 'B'
var3 BYTE 'C'
var4 BYTE 'D'
.code
main proc
;phase1
mov al, var1; store 'A'
mov ah, var4; store 'D'
mov var1, ah; move 'D' to var1
sub ah, 1; make ah 'C'
mov var4, ah; move 'C' to var4
sub ah, 1; make ah 'B'
mov var3, ah; move 'B' to var3
mov var2, al; 'mov al to var2
;var1 BYTE 'D'
;var2 BYTE 'A'
;var3 BYTE 'B'
;var4 BYTE 'C'
;phase2
mov ah, var1; store 'D'
mov al, var2; store 'A'
; this is where I want to shift al and ah left two bytes
; once the first two bytes of eax equal 'DA' move 'B' 'C'
; into ah and al
mov ah, var3; store 'B'
mov al, var4; store 'C'
;eax should read 'DABC' = 44414243
invoke ExitProcess,0
main endp
end main
如果您不能像正常人一样使用shl eax, 16
,您的其他选择包括:
add eax,eax
重复 16 次(糟糕,慢),循环部分展开或完全展开。- 以偏移量存储/重新加载:也很慢,但仅用于延迟(存储转发停顿)。吞吐量还可以,而延迟非常接近与典型现代 x86 上的 16x
add
方式相同的 16 个周期。
sub esp, 16 ; reserve some stack space.
...
mov [esp+2], ax ; 2 byte store
mov eax, [esp] ; 4-byte reload with previous AX in the top half
mov ah, ... ; overwrite whatever garbage in the low 2 bytes
mov al, ...
x86 是小端 ,因此 load/store 的 EAX 到 addr
loads/stores AL 到相同的 addr
,和 AH 到 addr+1
.,高 2 个字节来自 addr+2 和 +3.
在写入 AH 和 AL 后读取 EAX 也会强制 CPU 合并部分寄存器,如果它从完整的 EAX 中分离重命名 AH(可能还有 AL),但很明显,如果你只限制自己ISA 的一小部分然后高性能不是您的首要目标。 (有关详细信息,请参阅
store-forwarding stall部分见Can modern x86 implementations store-forward from more than one prior store?
取决于你对新的低部分(新的 AH 和 AL)做了多少,你实际上可以在一个单独的寄存器(比如 DH 和 DL)中做它们,所以无序的 exec 可以得到开始了这项工作,没有对存储转发重新加载的错误依赖,尤其是在 CPUs 上,它们没有从 EAX 中单独重命名 AL(甚至 AH)。 (即 CPU 不是 Intel P6 系列的,例如顽皮的老 Nehalem)。
所以你会这样做
mov [esp+2], ax ; 2 byte store
mov eax, [esp] ; 4-byte reload with previous AX in the top half
mov dl, ...
mov dh, ...
... more computation with these two
mov ax, dx ; replace low 2 bytes of EAX
mov ax,dx
可能需要等待旧的 EAX 值“准备好”,即重新加载完成,因此它可以作为 运行 该指令的一部分合并到其中。 (在 Intel Sandybridge 系列和所有非 Intel CPUs 上。)所以这让 DL/DH 上的计算与存储转发延迟重叠。
明确一点,所有这些关于权衡的讨论都是关于性能,而不是正确性;我在这里展示的所有方法都是完全正确的。(除非我弄错了 :P)