我可以用变量值初始化Cx寄存器吗? 如下图所示
MOV Cx, varaible
如果不是,那么如何使用用户输入值动态初始化Cx?请帮忙!
答案 0 :(得分:3)
不是关于名字,而是关于心理形象。程序集中没有变量。
对于机器,只有寄存器,存储器,地址和访问存储器的指令。 Variables 是程序员的逻辑结构,他决定以这种方式编写代码 - 它将使用内存作为"变量"。但如果他决定不这样做,或者犯了错误,那么它就不会表现得多变,机器也不在乎。
例如,在您的代码中,您为"变量"分配内存。在.data
部分:
.Data
var DB ?
这将转换为符号var
,它有效地存入内存。它还将保留.data
部分中的单个字节,因此接下来定义到那里的任何内容都将在此之后分配。如果您要添加下一行var2 DB 13
,则var2
地址将等于var + 1
。您还可以使用相同的地址创建多个符号,如下所示:
.Data
var:
var2:
DB ?
通过这样的定义,var
和var2
符号都指向相同的内存地址。
它可能看起来像你的"变量"心理图像与此兼容,因此我将展示"只是记忆和#34;之间的另一个区别。和"变量":
MOV [var], AL ; store value in AL into memory at address "var"
; your MOV var, AL without brackets works only in MASM/TASM assemblers
; but it is not valid Intel syntax, I will use brackets for every memory access
这将AL
的8位值写入地址var
的内存中。到现在为止还挺好。现在你问:
MOV CX, [var]
这将编译并执行,但它不会按预期工作。因为您只将8位写入内存,而var
仅保留1个字节。但CX
是16位寄存器(由CH
组成高8位,CL
组成低8位),因此该指令将从地址var
的内存中读取两个字节。 x86是little-endian,因此当CPU使用16位值时,它将低8位映射为第一个字节(偏移+0),高8位映射为第二个字节(偏移+1)。因此,这将使用CL
和AL
存储的值CH
加载var
,这些值恰好存在于var2 DB 13
之后的内存中。如果您要在var
之后添加CH
,那么13
将等于值CX
,因此13*256 + <stored_AL>
总值将为{{1} }}。如果存储AL
为7,则为CX = 3335
(或十六进制格式0D07h
,这很好地显示了两个字节值,D
= 13,7
= 7 )。
因此,如果要将存储的8位值正确读入CX
,则必须将其从8位扩展到16位。如果您使用80386+指令集,则有专门的说明:
MOVZX cx,BYTE PTR [var] ; zero-extend value ("unsigned" arithmetic)
MOVSX cx,BYTE PTR [var] ; sign-extend value ("signed" arithmetic)
对于80386之前的CPU,您必须计算这样的值,一种可能的方法是:
XOR cx, cx ; clear all 16bits of CX to zero
MOV cl, [var] ; fetch only low 8 bits from memory
; CX is now zero-extended 16 bit value of [var] (like MOVZX)
MOV ch, [var] ; fetch 8 bit value into upper 8 bits of CX
SAR cx, 8 ; use right shift by 8 bits to sign-extend the value
; CX is now sign-extended 16 bit value of [var] (like MOVSX)
; this code is not optimal on 586+ CPUs, but then use MOVSX
这就是&#34;只是记忆&#34;之间的主要区别。和&#34;变量&#34;,程序集不会保护你,它会让你在变量之外读/写内存,编写正确的代码,考虑数据大小和分配是你的任务/保留足够的记忆。另外手动执行所有指针数学运算,即如果要创建单词数组(16位值),则必须将索引缩放* 2以计算正确的字节地址(而C / C ++将隐藏指针数学你,所以你只做[i],* 2由编译器内部完成。