MASM Assembly move 8 bit register to the 16 bit register (ie. mov cx, ch) [duplicate]

扶醉桌前 提交于 2019-12-01 03:24:28

问题


I decided to learn an assembly programming language. I am using this 8086 tutorial. At the bottom the exercise is to find an error in some instructions and one of them is

mov cx, ch 

I found some similar question on SO on this topic explaining how to achieve it but now I'd like to know why this operation is forbidden?

Let's assume I have 10d = 00001010b in CH and want to put it to CL and simultaneously erase CH. mov cx, ch seems to do it because it shows 10d as 16bit 00000000 00001010 and puts it respectively to CH and CL (entire CX)

What is wrong with it and why does given tutorial ask to find an error in this expression?


回答1:


The mov instruction is used to move between operands of the same size. What you want to is extend the 8-bit ch into the 16-bit cx. There are two instructions available for that purpose:

movzx cx,ch  ; zero-extends ch into cx. the upper byte of cx will be filled with zeroes
movsx cx,ch  ; sign-extends ch into cx. the upper byte of cx will be filled with the most significant bit of ch

Another way of accomplishing the same thing in this particular case would be:

shr cx,8  ; zero-extend
sar cx,8  ; sign-extend



回答2:


The problem is, that you're trying to move the contents of an 8 bit register ch into a 16 bit register cx. You can't do that because the registers are different sizes.

So I'd guess that you get an error message like "invalid combination of opcode and operands".

p.s: exchanged 8 and 16 above; the statement stays the same. Check for instance this overview. As you see, there is no combination of different register sizes defined. It means there doesn't exist any OPcode that represents mov cx, ch.




回答3:


You want to move the contents of CH to CX on an 8086.

On more recent processors, such as the 80286, you could just shift the value of CX right by 8 positions, with or without sign replication:

; zero extend ch into cx
    shr cx,8

; sign extend ch into cx
    sar cx,8

These instructions are not available on the 8088 or the 8086. You can must use CL to specify the shift count:

; zero extend ch into cx
    mov cl,8
    shr cx,cl

; sign extend ch into cx
    mov cl,8
    sar cx,cl

Yet this method is very slow because the shift by a variable number of positions takes multiple cycles per position.

Here is a faster method:

; zero extend ch into cx
    mov cl,ch
    xor ch,ch

; sign extend ch into cx
    mov cl,ch
    neg ch     ; set the carry flag if ch is negative
    sbb ch,ch  ; set all bits if ch was negative, clear them otherwise

If you can destroy AX, you can save code size by using cbw which is designed for this. On original 8086 and especially 8088, small = fast because code fetch was a major bottleneck. That's not true on modern x86, though.

; sign extend ch into ax
    mov   al, ch
    cbw                 ; sign-extend AL into AX
; optionally move back to cx
    xchg  cx, ax        ; smaller than mov cx, ax

To avoid destroying AX, you could do mov cl,ch ; xchg ax,cx ; cbw and stop there, or do a final xchg ax,cx to just sign-extend CH into CX and restore everything else. xchg with AX is a 1-byte instruction, and so is cbw and cwd (extend AX into DX:AX, e.g. before 16-bit idiv)

cbw is exactly like 386 movsx ax, al.




回答4:


just do it with simple instructions

mov cl,ch  ; copy high bits to low
xor ch,ch  ; clear high-bits

it is common in 16bit programming and it only takes 2 clock cycles.

The use of the movezx/movsx needs 3 clock cycles. Use

movsx cx,ch

for moving byte to word with sign-extension and

movzx cx,ch

to Move byte to word with zero-extension



来源:https://stackoverflow.com/questions/29716796/masm-assembly-move-8-bit-register-to-the-16-bit-register-ie-mov-cx-ch

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!