程序问答   发布时间:2022-06-01  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了如何移动 eax 寄存器中的值,ah 和 al 左 2 个字节? x86 组装大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

如何解决如何移动 eax 寄存器中的值,ah 和 al 左 2 个字节? x86 组装?

开发过程中遇到如何移动 eax 寄存器中的值,ah 和 al 左 2 个字节? x86 组装的问题如何解决?下面主要结合日常开发的经验,给出你关于如何移动 eax 寄存器中的值,ah 和 al 左 2 个字节? x86 组装的解决方法建议,希望对你解决如何移动 eax 寄存器中的值,ah 和 al 左 2 个字节? x86 组装有所启发或帮助;

我有一个关于如何在 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 和还剩下两个字节的位置? (问号,因为我不知道。)我相当确定我可以将正确的值添加回 ah 和 al 以完成解决方案。

我相信这样做的方法是向 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 是little-endian,因此将EAX 加载/存储到addr 将AL 加载/存储到相同的addr,将AH 加载/存储到addr+1。,高 2 个字节来自 addr+2 和 +3。

在写入 AH 和 AL 后读取 EAX 也将强制 CPU 合并部分寄存器,如果它与完整 EAX 分开重命名 AH(也可能是 AL),但很明显,如果你限制自己只使用 ISA 的一个很小的子集那么高性能不是您的首要目标。 (有关详细信息,请参阅 Why doesn't GCC use partial registers? 和 How exactly do partial registers on Haswell/Skylake perform? WriTing AL seems to have a false dependency on RAX,and AH is inconsistent。)

店铺转发摊位部分见Can modern x86 implementations store-forWARD from more than one prior store?


根据你对新的低部分(新的 AH 和 AL)做了多少,你实际上可能在一个单独的寄存器中做它们(比如 DH 和 DL),所以无序的 exec 可以开始这工作,没有对存储转发重新加载的错误依赖,特别是在不与 EAX 分开重命名 AL(甚至 AH)的 CPU 上。 (即不是 Intel P6 系列的 CPU,如硬皮的老 Nehalem)。

所以你会这样做

    mov  [esp+2],[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

@H_708_13@mov ax,dx 可能需要等待旧的 EAX 值“准备好”,即重新加载完成,以便它可以合并到它作为运行该指令的一部分。 (在英特尔 SAndybridge 系列和所有非英特尔 CPU 上。)因此,这让 DL/DH 上的计算与存储转发延迟重叠。

需要说明的是,所有关于权衡的讨论都是关于性能的,而不是正确性;我在这里展示的所有方法都是完全正确的。(除非我犯了错误:P)

大佬总结

以上是大佬教程为你收集整理的如何移动 eax 寄存器中的值,ah 和 al 左 2 个字节? x86 组装全部内容,希望文章能够帮你解决如何移动 eax 寄存器中的值,ah 和 al 左 2 个字节? x86 组装所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。