实验十 第一个子程序,大家帮忙看看代码
assume cs:codesgdatasg segment
db 'welcome to masm!',0 ;定义一个字符串
datasg ends
stacksg segment ;定义一个空栈
dw 8 dup(0)
stacksg ends
codesg segment
start: mov dh,8h
mov dl,3h
mov cl,2h
mov ax,datasg
mov ds,ax
mov ax,stacksg
mov ss,ax
mov sp,16
mov si,0
call show_str ;调用子函数
mov ax,4c00h
int 21h
show_str:push ax ;子函数,为了保险把所有的寄存入栈,因为我们不知道子程序会不会用到主程序里的寄存器
push bx
push si
push di
push cx
push bp
mov bx,0
mov bl,cl
mov ax,0ah
mul dh ;乘以dh行,主程序提供dh
add ax,0b800h
mov es,ax ;定义目标段地址为b800+dh*0ah
mov bp,1 ;计算偏移地址,第dl列的内存地址
mul dl
s: mov cl,
mov ch,0 ;判断cx是否为0,为0就跳转到ok
jcxz ok
mov al,ds:
moves:,al ;写入字符
moves:,bl ;写入颜色
inc si
add bp,2
jmp short s ;跳转到标号s
pop di
pop si
pop bx
pop ax
ok:ret
codesg ends
end start
自己写的,经编译没有错误,但是运行后报错,不知道动了系统的什么内存。求指正。
编译没错排除语法问题,剩下考虑逻辑问题和系统问题。系统是否Win7?是否权限不够?报错的提示是什么内容呢? 小甲鱼 发表于 2012-2-14 12:05 static/image/common/back.gif
编译没错排除语法问题,剩下考虑逻辑问题和系统问题。系统是否Win7?是否权限不够?报错的提示是什么内容呢?
C:\Documents and Settings\Administrator\桌面\cuowu.jpg 小甲鱼 发表于 2012-2-14 12:05 static/image/common/back.gif
编译没错排除语法问题,剩下考虑逻辑问题和系统问题。系统是否Win7?是否权限不够?报错的提示是什么内容呢?
NTVDM CPU遇到无效指令。
cs:cdb8 IP:02b1, op: ff ff ff ff ff 选择关闭终止。 你的子程序show_str错的太多,还是用我的这个吧!
;名称:show_str
;功能:在指定的位置,用指定的颜色,显示一个用0结束的字符串。
;参数:dh=行号(取值范围0—24),dl=列号(取值范围0-79),cl=颜色,
;ds:si指向字符串的首地址。返还:无。
;应用举例:在屏幕的8行3列,用绿色显示data段中的字符串。
assume cs:codesg,ds:datasg,ss:stacksg
datasg segment
db 'welcome to masm!',0 ;定义一个字符串
datasg ends
stacksg segment
dw 8 dup(0) ;定义一个空栈
stacksg ends
codesg segment
start: mov dh,8h
mov dl,3h
mov cl,2h
mov ax,datasg
mov ds,ax
mov ax,stacksg
mov ss,ax
mov sp,16
mov si,0
call show_str ;调用子函数
mov ax,4c00h
int 21h
show_str: ;显示字符串的子程序(定义开始)。
push cx
push si
mov al,0a0h ;每行有160个字节,转换成16进制为A0。
dec dh ;行号在显存中下标从0开始,所以自减1.
mul dh ;相当于从第(n-1)*0A0H个Byte单元开始......
mov bx,ax ;定位好的位置偏移地址存放在bx里(行)
mov al,2 ;每个字符占两个字节
mul dl ;定位列,结果ax存放的是定位好的列的位置
sub ax,2 ;列号在显存中下标从0开始,又因为偶字节存放字符,所以减2
add bx,ax ;此时bx中存放的是行与列号的偏移地址
mov ax,0B800h;显存开始的地址
mov es,ax ;es中存放的是显存的第0页(共0--7页)的起始的段地址
mov di,0 ;di指向显存的偏移地址,确定指向下一个要处理的字符的位置
mov al,cl ;cl是存放颜色的参数,这时候al存放颜色了,因为cl下边要用来临时存放要处理的字符
mov ch,0 ;下边cx存放的是每次准备处理的字符
s: mov cl,ds: ;ds:指向“Welcome to masm!”,0
jcxz ok ;当cl的值为0时候,cx == 0, 则发生跳转,到OK处结束处理!
mov es:,cl ;偶地址存放字符
mov es:,al ;奇地址存放字符的颜色属性
inc si
add di,2 ;指向了下个字符
jmp short s ;无条件跳转,jcxz是离开的关键跳!
ok:pop si
pop cx
ret ;显示字符串的子程序[定义结束]
codesg ends
end start
厉害。。向各位大师学习来了。。 我用5楼的调试,为为什么显示器不显示字符呢 我自己编的程序,调试的时候 有时候显示字符,有时候不显示字符,请问是为什么
assume cs:code
data segment
db'welcome to masm!',0
data ends
code segment
start: mov dh,8
mov dl,3
mov cl,2
mov ax,data
mov ds,ax
mov si,0
call show_str
mov ax,4c00h
int 21h
show_str:
mov ax,0b800h
mov es,ax
mov ax,160
mul dh
push ax
mov al,dl
mov bl,2
mul bl
pop bx
add ax,bx
mov di,ax
s:
mov cl,
mov ch,0
jcxz ok
mov bl,
mov byte ptr es:,bl
inc di
mov cl,2
mov byte ptr es:,cl
inc di
inc si
jmp short s
ok: ret
code ends
end start 本帖最后由 莫名其妙 于 2012-2-24 20:35 编辑
mov bx,0
mov bl,cl; 你这句话的意思应该是保存CL吧其实 下面完全可以用(看绿字部分)
mov ax,0ah; 这是 0a0h
mul dh ;乘以dh行,主程序提供dh
add ax,0b800h
mov es,ax ;定义目标段地址为b800+dh*0ah
mov bp,1 ;计算偏移地址,第dl列的内存地址
mul dl ;这么乘一下 是什么意思? ax*dl? ax是多少?
s: mov cl,
mov ch,0 ;判断cx是否为0,为0就跳转到ok
jcxz ok
mov al,ds:
moves:,al
;mov cl,2
;mov es:,cl
moves:,bl
;写入颜色
inc si
add bp,2
jmp short s ;跳转到标号s
莫名其妙 发表于 2012-2-24 20:12 static/image/common/back.gif
mov bx,0
mov bl,cl; 你这句话的意思应该是保存CL吧其实 下面完全可以用(看绿字部分)
...
绿字不能用cl ,因为cx要用于判断是否为零。只能先把cl放进另外一个寄存器。 莫名其妙 发表于 2012-2-24 20:12 static/image/common/back.gif
mov bx,0
mov bl,cl; 你这句话的意思应该是保存CL吧其实 下面完全可以用(看绿字部分)
...
mov bp,1
mul dl
这个指令是用于计算每行的第几列,不过,好像错了,每列2个字符才对。 有点点看不懂…… 留个坐 厉害!!! 老师们都好厉害!
这个指令是用于计算每行的第几列,不过,好像错了,每列2个字符才对。
页:
[1]