assembly 将DB变量中的字节值加载到16位寄存器中(带符号或零扩展字节)

oo7oh9g9  于 2023-01-26  发布在  其他
关注(0)|答案(2)|浏览(135)

我正在使用MASM编译器和DOSBOX。我想把变量的值保存到寄存器中。我想把num1的值保存到cx寄存器中。我该怎么做呢?

.MODEL SMALL
.STACK  50H
.DATA
num1 db '5'
    NL  DB  0DH, 0AH, '$'        
    msg     db ?,0AH,0DH,"Enter an odd number between 0 to 10:$"
     nxtline db 0Ah,0DH,"$"
.CODE
MAIN PROC
    MOV AX, @DATA
    MOV DS, AX
    
    
            
              LEA DX,msg     
              mov ah,9
              int 21H
              LEA DX,nxtline    
              mov ah,9
              int 21H
              
              MOV AH,1                    
              INT 21H 
              LEA DX,nxtline    
              mov ah,9
              int 21H
              
              
              
       mov bl,al   ;save the value from input
              mov num1,bl
               LEA DX,num1     
              mov ah,9
              int 21H
              mov cl,al 
              
   main endp
   end main
xxslljrj

xxslljrj1#

用户在AL中输入的值正在丢失。使用以下命令输入一个字符:

MOV AH,1                    
          INT 21H

字符存储在AL中,但在将值保存到BL中之前,显示一个换行符:

LEA DX,nxtline    
          mov ah,9
          int 21H

AL中的值消失了,因为这个中断使用AL来显示一个字符串,解决方法是在显示换行符之前**将值保存在BL中:

MOV AH,1                    
          INT 21H 
   mov bl,al   ;save the value from input
          LEA DX,nxtline    
          mov ah,9
          int 21H

**编辑:**将值移入CX

xor cx,cx       ;CLEAR CX.
mov cl,bl       ;MOVE CHAR INTO CL.
sub cl, 48      ;CONVERT CHAR TO DIGIT, EXAMPLE: '5' -> 5.
628mspwn

628mspwn2#

顺便说一句:你发布的源代码,不能编译(num1没有定义)。
一般来说,要将值从存储器加载到寄存器中,可以使用:

mov reg8|16|32|64,[<memory_address>]

示例:

num1: db 7

汇编程序将其编译为包含值7的单字节,并将标记num1记录到符号表中,标记num1存在,指向该字节。

num2: dw 0x0809

这将被编译为两个字节:09 08(数字的最低有效部分首先进入内存,因此09位于num2地址,08位于num2+1地址)。num2标签放入符号表,指向定义字的第一个字节(值09)。

mov bl,[num1]   ; loads value 7 into bl
mov cx,[num2]   ; loads value 0x0809 (8*256+9 = 2057 in decimal) into cx
mov al,[num2]   ; loads value 9 into al
mov ah,[num2+1] ; loads value 8 into ah = now ax contains 2057. (ax = ah:al)
mov dx,[num1]   ; will load dl with 7, and dh with something what is after it
  ; if you wanted "num1", then this is bug, as "num1" is only 1 byte "wide"
  ; and dx is 16 bit register, so it's two bytes wide.

要将8位值从bl加载到16位寄存器cx中,您有几种选择,但都遵循相同的原则,您必须将8位值扩展为16位"宽"。

mov cl,bl   ; set's lower 8 bits of cx to bl, doesn't care about upper 8 bits
  ; ^ unless done on purpose, this is bug, as "cx" has unexpected value

movzx cx,bl ; "zx" = zero-extend, value 0xFE (254) will become 0x00FE (254)
  ; recommended way for 386+ code (does not exist on 8086-80286 CPUs)

movsx cx,bl ; "sx" = sign-extend, so value 0xFE (-2) will become 0xFFFE (-2)
  ; recommended way for 386+ code (does not exist on 8086-80286 CPUs)

xor cx,cx   ; cx = 0
mov cl,bl   ; same as first example, but ch was set to zero with previous ins.
  ; recommended way for 8086 code

mov ch,bl  ; ch = bl, cl undefined
sar cx,8   ; cx = sign extended bl to 16 bits (bl=0xFE will set cx=0xFFFE)
  ; "recommended" way for 8086 code (not really, but who cares about 8086 anyway)
  ; for al -> ax sign extension there's specialized CBW instruction

mov cl,bl      ; cl = bl, ch undefined
and cx,0x00FF  ; AND with 0x00FF will clear ch, and keep cl
  ; not recommended (slower), just example that any valid math works of course

为了验证这些工作,在调试器中启动代码,并观察寄存器值在跳过每个指令后的变化。
您更新的问题是"如何在x86汇编程序中显示数字"。
参见https://stackoverflow.com/tags/x86/info,搜索"如何处理多位数字?"
但首先你可能还应该搜索什么是ASCII,"字符串"在计算机中是如何工作的,以及它们与寄存器中的数字值有何不同。
在大多数平台上(DOS也是),你不能只执行mov cx,1234并在屏幕上用一条指令将其打印为字符串"1234"。你必须首先在某个内存缓冲区中构建一个包含五个字符1234$的ASCII字符串(来自cx中的16b数值),然后你可以使用int 21h,9来显示该字符串。

相关问题