Assembly 'move byte ptr`、'move word ptr`、'mov var+;1、mov[var]和#x2B;1.

Assembly 'move byte ptr`、'move word ptr`、'mov var+;1、mov[var]和#x2B;1.,assembly,tasm,emu8086,Assembly,Tasm,Emu8086,我读了一些关于 “ptr是做什么的?” “什么是[]呢?”但我发现理解下面的问题没有什么帮助 Title : Program failed to comprehend .model small .stack 100h .data Msg db 10,13, 'Zahid. $' .code .startup ; Initialising data segment mov ax, @data mov dx, ax ;Before opera

我读了一些关于
“ptr是做什么的?”
“什么是[]呢?”
但我发现理解下面的问题没有什么帮助

Title : Program failed to comprehend
.model small
.stack 100h
.data
     Msg db 10,13, 'Zahid. $'   
.code
.startup
     ; Initialising data segment
      mov ax, @data
      mov dx, ax
    ;Before operation displaying message
     mov dx, offset msg
     mov ah,09h
     int 21h

      mov msg , 'A'          ; Writing on memory specified by msg thats OK -> A
      mov msg+1 , 'R'     ; Confusion as writing on memory specified by msg then add 1(not 8bits next address write) -> A
      mov [msg]+2, 'I'     ; confusion: Writing on memory specified by msg then add 2 value to that address write-> I
      mov byte ptr [msg+3] , 'F'      ; Ok with me, writing on byte memory specified by msg+3 -> F 
      mov word ptr [msg + 4], '.'      ; Confused again as writing on word memory specified by msg+4, '.' Will it write ascii on the two bytes-> .
      mov msg[5] , '$'   ; Not confused on this.

   ;Print var
    mov dx, offset msg
    mov ah,09h
    int 21h
 
    ;Exit Code.
    mov ah,04ch
    xor al,al
    int 21h
     
Ends
输出:
扎希德。阿里夫


请解释操作,因为我认为它不应该在汇编中打印“ARIF”?

语法取决于特定的汇编程序。Emu8086主要采用MASM方言,这在规则上相当宽松,并允许使用几种不同的语言

如果您习惯了一些高级编程语言,这可能会让您感到困惑,为什么语法不是一成不变的,以及如何处理asm中的这种混乱

但对于asm程序员来说,这很少是一个问题,因为在汇编程序中,您不会使用运算符和不同的值构建一些运行时表达式,源代码中的指令通常是1:1映射到CPU指令之一,并具有CPU中存在的特定指令的确切参数和选项

x86上的本身就有点乱,因为它是用于许多不同指令操作码的单助记符“MOV”,但在您的示例中只使用了两条指令:
MOV r/m8、imm8
带操作码
C6
用于存储字节值,以及
MOV r/m16、imm16
带操作码
C7
用于存储字值。在所有情况下,
r/m
部分都是绝对偏移量的内存引用,绝对偏移量是在编译时计算的

因此,如果
msg
是内存地址
0x1000
的符号,那么问题中的这些行编译为:

; machine code  | disassembled instruction from machine code

C606001041        mov byte [0x1000],0x41
将字节值
0x41
A'
)存储到地址
ds:0x1000
的内存中。
C606
MOV[offset16],imm8
指令操作码,
0010
字节是
0x1000
offset16本身(小端),最后
41
是imm8值
0x41
。默认情况下,段
ds
将用于计算完整的物理内存地址,因为在该指令之前没有段覆盖前缀

C606011052        mov byte [0x1001],0x52
C606021049        mov byte [0x1002],0x49
C606031046        mov byte [0x1003],0x46
C70604102E00      mov word [0x1004],0x2e
C606051024        mov byte [0x1005],0x24
其余的行都是相同的故事,以特定的内存偏移量写入字节值,在内存中逐字节进行,覆盖其中的每一行

与其他行类似,mov word ptr[msg+4]的细微差别是“.,它的目标内存地址是
ds:0x1004
,但存储的值是
imm16
,即
word
值,等于
0x002E
”。,因此使用不同的操作码
C7
,立即数需要两个字节
2E 00
。这个将用字节
2E
覆盖地址
ds:0x1004
处的内存,用字节
00
覆盖地址
ds:0x1005
处的内存

因此,如果地址
msg
ds:0x1000
在我的示例中)处的内存位于开始位置:

0x1000: 0A 0D 5A 61 68 69 64 2E 20 24  ; "\n\rZahid. $"
每次执行
MOV
后,它都会变为:

0x1000: 41 0D 5A 61 68 69 64 2E 20 24  ; "A\rZahid. $"
0x1000: 41 52 5A 61 68 69 64 2E 20 24  ; "ARZahid. $"
0x1000: 41 52 49 61 68 69 64 2E 20 24  ; "ARIahid. $"
0x1000: 41 52 49 46 68 69 64 2E 20 24  ; "ARIFhid. $"
0x1000: 41 52 49 46 2E 00 64 2E 20 24  ; "ARIF.\0d. $"
这个词确实覆盖了两个字节,都是
'h'
(带点)和
'i'
(带零)

并且该零被再次改写为美元符号(DOS
int21h
service
ah=9
的字符串终止符)

一般来说,宽松的语法不是问题,因为您无法构建自己的指令,汇编程序将猜测现有指令中的哪一条适合,并将您拥有的任何表达式编译到其中。x86上没有像
mov[address1]和[address2]这样的指令,value
在两个不同的内存位置存储相同的值,或者
mov[address]+2
会在
address
的内存值中添加两个(这可能与
add[address],2
有关,这取决于数据大小)

所以
mov msg+1,…
只能是内存地址
msg+1
,在x86指令集中没有其他有意义的可能性。数据大小
字节
从标签
msg:
后使用的
db
指令中扣除,这是MASM和emu8086汇编程序的特点,大多数其他汇编程序不将任何定义的标签(符号)与其后使用的指令链接,即普通汇编程序中没有“类型”的符号。对于那些
mov msg+1,'R'
可能以语法错误结束,但不是因为左侧有问题,而是他们不知道
'R'
值应该有多大(多少字节)

我个人最喜欢的NASM会报告另一个错误,因为它需要内存访问周围的括号,因此在NASM中,只有
mov[msg+2],…
才有效(允许在MASM中使用“字节ptr”之类的大小修饰符,但不允许“ptr”:
mov byte[msg+2],但在MASM/emu8086中,您使用的所有变体都是具有相同含义的有效语法,产生16b偏移量的内存引用

汇编程序也不会生成两条指令而不是单个指令(异常可能是某些汇编程序中的特殊“伪指令”,这些指令编译成几个本机指令,但在x86程序集中并不常见)

一旦你知道目标CPU指令集,什么指令存在,你就可以很容易地从模糊的语法中猜出将产生哪个目标指令

或者,您可以很容易地在“调试器反汇编”窗口中进行检查,因为反汇编程序对特定指令只使用单一的语法方式,而不知道源格式的模糊性

它将在两个字节上写入,这是MASM中指定的
字PTR
。但值仅为
。=0x2E
。但是
0x2E
即使是16位值也是完全有效的,只需用零扩展到
0x002E
,这是汇编程序用于此行的值

将来,如果您不确定特定的东西是如何组装的,以及它对CPU/内存状态的影响,只需使用emu8086调试器即可
0x1000: 41 52 49 46 2E 24 64 2E 20 24  ; "ARIF.$d. $"
 mov word ptr [msg + 4], '.'
   ; Confused again as writing on word memory specified by msg+4,
     '.' Will it write ascii on the two bytes-> .