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'
(带零)
并且该零被再次改写为美元符号(DOSint21h
serviceah=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-> .