我正在努力了解装配。今天的主题是:“存储和增加int变量和打印数字”:)
所以这是我的代码
dane segment
count db 0
dane ends
code segment
start:
inc byte ptr ds:[count]
inc byte ptr ds:[count]
inc byte ptr ds:[count]
mov dl,ds:[count]
mov ah,2
int 21h
mov ah,4ch
int 21h
code ends
end start
当我编译并运行时,我收到了这个错误:
仅当count
递增多次时才会发生。
我做错了什么?
有人可以解释为什么我不能简单地写:
inc count
另外,为什么我在递增值时必须放byte ptr
,但如果我将它复制到dl
寄存器则不行?
答案 0 :(得分:3)
编辑:重写并添加了文字,添加了代码(适用于MASM 6.11):
在x86中,你需要指定内存操作数的大小,否则会出现歧义。您必须使用byte ptr
,word ptr
等告诉汇编程序操作数的大小。因此inc byte ptr ds:[count]
需要byte ptr
。 inc word ptr ds:[count
是不同的指示。
mov dl,ds:[count]
不需要byte ptr
,因为dl
是一个8位寄存器,因此内存操作数的大小始终相同,一个字节(8位)。< / p>
要打印字符,您需要先将数字转换为字符串(或者将数字转换为小于10的数字)。否则,您将打印具有ASCII代码3的控制字符ETX(请参阅ASCII table)。对于小于10的数字,以十进制打印是微不足道的,只需添加“0”(30h
),如下所示:< / p>
mov dl,ds:[count] add dl,'0' ; add dl,30h
在x86程序集中以十进制打印是经常被问到的,例如参见Is this code correct (Number plus number, then print the result)以获得想法。
编辑: EXE文件也需要一个堆栈段。
DOS EXE文件需要有一个堆栈段。使用MASM 6.11进行汇编时不会发出任何警告或错误,基本上是dosexe.asm
(将dosexe.asm替换为汇编代码文件名)。
但是与ML(ml dosexe.obj
)的链接会发出以下警告:
LINK : warning L4021: no stack segment
因此,需要添加堆栈段,将以下行添加到源的顶部。
.model small .stack 4096
数据段定义也存在一些问题,我也解决了这个问题。
整个固定汇编代码可能是这样的(在MASM 6.11中有效):
.model small .stack 4096 .data count db 0 .code start: mov ax,seg count mov ds,ax inc byte ptr ds:[count] inc byte ptr ds:[count] inc byte ptr ds:[count] ; this code does the printing in decimal without needing to reverse ; the string, by dividing the divisor. 100/10 = 10 mov bl,100 ; original divisor. mov al,ds:[count] print_loop: xor ah,ah ; clear top 8 bits of the dividend (in ax). div bl ; divide ax by bl. quotient in al, remainder in ah. mov dl,al ; the value to be printed with ah = 2, int 21h mov al,ah ; remainder gets divided in the next loop. test dl,dl ; check if number is zero jz not_print ; don't print leading zeros. add dl,'0' ; convert to ASCII numeric characters range. ; '0' = 0x30 = 48 push ax mov ah,2 int 21h ; print the value, according to Ralf Brown's pop ax ; interrupt list returns al. not_print: push ax mov al,bl xor ah,ah mov bl,10 ; divide the divisor by 10. div bl mov bl,al ; the new divisor. pop ax test bl,bl jnz print_loop mov ah,4ch int 21h end start
答案 1 :(得分:0)
[quote] mov dl,ds:[count]不需要字节ptr,因为dl是一个8位寄存器,因此内存操作数的大小总是相同的,一个字节(8位)。[/报价]
此外,此操作不需要段覆盖前缀,因为DS是此操作的默认段。 =&GT; mov dl,[count]
编辑:
定义名为具有段属性
的名称的程序段http://msdn.microsoft.com/de-de/library/d06y3478%28v=vs.80%29.aspx
name SEGMENT [[READONLY]] [[align]] [[combine]] [[use]] [[characteristics]] ALIAS(string) [['class']]
statements
name ENDS
使用细分名称的示例:
CODE SEGMENT use16 'CODE'
assume cs:CODE,ds:DATEN,ss:STAPEL
org 100h
START:
mov ax, DATEN
mov ds, ax
; your instructions
CODE ends
DATEN SEGMENT use32 'DATA'
org 0
VALUE DD ?
DATEN ends
STAPEL SEGMENT use16 STACK 'STACK'
DB 10h dup (0)
STAPEL ends
end
如何使用细分和指令:
http://cs.smith.edu/~thiebaut/ArtOfAssembly/CH08/CH08-3.html
...
为了使用MASM 6链接16位应用程序,我们需要一个其他链接器。
ftp://ftp.microsoft.com/softlib/mslfiles/lnk563.exe
德克