. : : Assembly Language : : .  |  首页  |  我提出的问题  |  我参与的问题  |  我的收藏  |  消息中心   |  游客  登录  | 
刷新 | 提问 | 未解决 | 已解决 | 精华区 | 搜索 |
  《汇编语言》论坛 ->CALL和RET指令
  管理员: assembly   [回复本贴] [收藏本贴] [管理本贴] [关闭窗口]
主题 : :  一个有趣的现象,入栈了不会出栈!!!  [已解决] 回复[ 9次 ]   点击[ 490次 ]  
powlin1991
[帖 主]   [ 发表时间:2012-04-09 13:09 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:5
注册日期:2012-03-22 15:34
;实验10.1的问题,有详细注释,显示后的颜色有点问题,麻烦各位看看。

;小疑问:程序中没有使用栈,但是没有错误,难道内存自动定义一个栈?
;在s2下面还有一个小错误。。。整个程序还存在两个警告!!!
assume cs:code
data segment
    db 'Welcome to masm!',0
data ends
;stack segment        ;原代码中没有定义栈
;    db 16 dup (0)
;stack ends

code segment
start:    mov dh,8        ;显存的行
    mov dl,3            ;显存的列
    mov cl,2        ;颜色
    mov ax,data
    mov ds,ax
    ;mov ax,stack        ;原代码中没有定义栈
    ;mov ss,ax
    ;mov sp,16
    mov si,0
    mov bx,0        ;自己加的寄存器,貌似原代码没有bx
    call show        ;跳转指令

    mov ax,4c00h        ;返回指令
    int 21h

show:    
    mov ax,0B800h        ;显存段地址
    mov es,ax
    mov al,160        ;每行160个字节
    mul dh            ;8位运算,储存在ax中
    mov bx,ax        ;寄存相乘后的结果,作为es的偏移地址使用
    add bx,160        ;加160是因为显示器貌似不是从第一行开始显示的

   s2:    push cl            ;cl入栈是为了保存颜色
    mov ch,0        ;让ch赋值为0
    mov cl,ds:[si]        ;把数据段中的字节赋值到cl中
    jcxz s1            ;cx不为0,则继续向下运行,否则跳转到s1
    mov es:[bx + 4],cl    ;把cl赋值到显存
    pop cl            ;将保存的颜色出栈,准备使用            (但是貌似没有出栈,运行后的颜色各不相同)
    mov ch,cl;    mov ch,2;    ;颜色保存到ch中(想不通为什么这里写mov ch,2就是对的,这样写就是错的。。。)
    mov es:[bx + 5],ch    ;ch赋值给高位(高位保存颜色,低位保存字节)
    inc si
    add bx,2
    loop s2            ;s2循环

s1:    ret            ;跳到返回指令处

    code ends
    end start
tomato
[第1楼]   [ 回复时间:2012-04-09 23:37 ]   [引用]   [回复]   [ top ] 
荣誉值:405
信誉值:0
注册日期:2008-01-19 14:51
"push cl"这条指令的语法有问题,栈是字操作,不可以是字节操作。
tomato
[第2楼]   [ 回复时间:2012-04-09 23:38 ]   [引用]   [回复]   [ top ] 
荣誉值:405
信誉值:0
注册日期:2008-01-19 14:51
“pop cl”这条指令同样有问题。
tomato
[第3楼]   [ 回复时间:2012-04-09 23:44 ]   [引用]   [回复]   [ top ] 
荣誉值:405
信誉值:0
注册日期:2008-01-19 14:51
“;小疑问:程序中没有使用栈,但是没有错误,难道内存自动定义一个栈? ”

栈的定义,其实就是设置栈段寄存器的值,我们的程序定义栈段也就是将栈段寄存器的值设置为我们程序分配好的那段栈空间,如果我们的程序中没有定义栈段,那么栈空间就是当前栈段寄存器指向的栈空间。如果对栈进行操作就是对这段空间进行操作。
powlin1991
[第4楼]   [ 回复时间:2012-04-10 12:22 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:5
注册日期:2012-03-22 15:34
回复:[第3楼]
------------------
感谢楼上的回答,我修改的程序如下:
麻烦看下思路还有没有问题,刚开始学子程序,可能在格式上会有些欠佳。
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                ;跳转指令
        mov ax,4c00h                ;返回指令
        int 21h

show:        
        mov bx,0
        push cx
        mov ax,0B800h                ;显存段地址
        mov es,ax
        mov al,160                ;每行160个字节
        mul dh                        ;8位运算,储存在ax中
        mov bx,ax                ;寄存相乘后的结果,作为es的偏移地址使用
        add bx,160                ;加160是因为显示器貌似不是从第一行开始显示的

        dec dl                        ;列减1
        mov al,2                ;做乘法
        mul dl                        ;第三列在第四字节上,(3-1)*2 = 4
        add bx,ax                ;bx作为显示第一个字节的偏移地址

   s2:        mov ch,0                ;让ch赋值为0
        mov cl,ds:[si]                ;把数据段中的字节赋值到cl中
        jcxz s1                        ;cx不为0,则继续向下运行,否则跳转到s1
        mov es:[bx],cl                ;把cl赋值到显存
        pop cx                        ;将保存的颜色出栈,准备使用            (但是貌似没有出栈)
        mov es:[bx + 1],cl        ;cl赋值给高位(高位保存颜色,低位保存字节)
        inc si                        ;数据段中的偏移地址加1
        add bx,2                ;显存中偏移地址加2
        push cx                        ;cx入栈,循环了以后出栈
        jmp s2                        ;s2循环

s1:        pop cx                        ;没有写这句话,栈中还有其他数据,所以先出来的不是IP
        ret                        ;跳到返回指令处

        code ends
        end start
tomato
[第5楼]   [ 回复时间:2012-04-10 23:04 ]   [引用]   [回复]   [ top ] 
荣誉值:405
信誉值:0
注册日期:2008-01-19 14:51
结果正确了,应该就没什么问题了。
powlin1991
[第6楼]   [ 回复时间:2012-04-10 23:19 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:5
注册日期:2012-03-22 15:34
回复:[第5楼]
------------------
再问个栈的问题,如果是内存分配了一个空间做栈,那是不是跟在data下呢?我觉得不是,因为跟在data下,入栈太多可能导致要冲掉原来数据,所以内存肯定分配了一个安全区域,但知道在哪里么?
powlin1991
[第7楼]   [ 回复时间:2012-04-10 23:27 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:5
注册日期:2012-03-22 15:34
所以SS和DS要不同,就不会导致栈出现溢出而冲掉data的数据了,这样理解对吧?
tomato
[第8楼]   [ 回复时间:2012-04-11 00:09 ]   [引用]   [回复]   [ top ] 
荣誉值:405
信誉值:0
注册日期:2008-01-19 14:51
这个要看程序加载的时候栈段寄存器的值是如何设置的。
powlin1991
[第9楼]   [ 回复时间:2014-02-17 14:21 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:5
注册日期:2012-03-22 15:34
此贴由 贴主 于 [ 2014-02-17 14:21 ] 结贴。 结贴原因:问题已解决
得分情况: 8楼(tomato):16分  
此问题已结贴!
    Copyright © 2006-2024   ASMEDU.NET  All Rights Reserved