assembly 如何编写一个仅使用3条指令和一个8位寄存器(8086指令集)循环256次的代码?

yyhrrdl8  于 2022-12-19  发布在  其他
关注(0)|答案(1)|浏览(135)

这是我的一位教授之前提出的问题,我假设8位寄存器是CL或CH。我通过将01H移到CH寄存器来使其工作,但我想知道是否有其他方法可以做到这一点,因为在运行代码时,我在技术上将16位CX寄存器作为一个整体使用。
我的参考代码:

MOV CH,01H
L1:INC AX    ;to keep count
LOOP L1
4ktjp1zp

4ktjp1zp1#

你是对的,你的代码使用了16位CX。更糟糕的是,它依赖于CL在这个代码段执行之前为零!一个从零开始的8位循环计数器将在256次递减(或递增)后返回零。

mov  al, 0     ; uint8_t i = 0.   xor ax,ax is the same code size but zeros AH
loop_top:             ; do {
   dec  al
   jnz  loop_top  ; }while(--i != 0)

这个问题中没有任何内容表明循环内部需要任何工作;这只是一个空的延迟环路。

效率说明dec axdec al小,loop rel8dec/jnz更紧凑。因此,如果您针对真实的的8086或8088进行优化,您会希望保持循环体更小,因为它比循环前面的代码运行的次数更多。当然,如果您实际上只想延迟,这将延迟更长的时间,因为代码获取将占用更多的内存访问。对于mov ax, 256(3字节)与xor ax,ax(2字节)或mov al, 0(2字节),总代码大小是相同的。

这对于任何8位寄存器都是一样的; AL对于这些指令中的任何一条都不是特殊的,所以您通常希望让它自由地用于那些可以受益于其特殊编码的东西,比如cmp al, imm8在2个字节中而不是通常的3个字节。
mov al, 0 vs. xor al,al-在许多现代CPU上都存在错误依赖。mov ah,0可能避免了对Skylake的错误依赖;至少mov从另一个寄存器执行,但可能不是立即数。参见 * How exactly do partial registers on Haswell/Skylake perform? Writing AL seems to have a false dependency on RAX, and AH is inconsistent *。无论如何,异或归零通常对字节寄存器没有用。)

相关问题