读书人

王爽lt;汇编语言gt;课件设计解决方法

发布时间: 2012-04-13 13:50:24 作者: rapoo

王爽<汇编语言>课件设计
我是prolove_000,郁闷了,散分散太多了...变得不能发帖.
问题:
为什么debug不能调试呢?调试到mov ch,0就出现强制退出的状况...

Assembly code
assume cs:code,ds:data,ss:stackdata segment        db '1975','1976','1977','1978','1979','1980','1981','1982','1983'        db '1984','1985','1986','1987','1988','1989','1990','1991','1992'        db '1993','1994','1995',0        dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514        dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000,0        dd 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226,11542,14430,15257,17800,0        dw 5,3,42,104,85,210,123,111,105,125,140,136,153,211,199,209,224,239,260,304,0data endsstack segment    dw 8 dup(0)stack endscode segmentstart:    mov ax,data        mov ds,ax        mov bx,0        mov ax,stack        mov ss,ax        mov sp,16        mov ax,0b8000h                ;把显存地址放入ax寄存器中        mov es,ax                    ;再把ax中的显存地址放入es中        mov di,0                    ;把di设置控制ds中的列        mov si,0                    ;控制es的行        call pw                mov ax,4c00h        int 21h        pw:        push bx        push di        push si        push cx        push bx        mov cl,[bx]                    ;把[bx]=0这个地址中的内容存放到cl中        mov ch,0        mov es:[si],cl                ;把cl的内容存放到        jcxz pe        mov dl,0A0h                    ;显存中一行有160个字节,所以存到cx中        mul dl                        ;因为一行有160个字节,所以乘以cx可以把光标定位到下一行        mov si,ax                    ; 把光标定位到下一行起始地址        inc bx        inc si        jmp short pwpe:        mov si,0                    ;把si光标从新定位到0这个位置        mov si,0ah                    ;把光标设定到第一行第10个字节处        mov dx,ds:[bx]                    ;把data段中定义的dword数据的高字节[bx]存放到dx中        mov ax,ds:[bx+4]                ;把data段中定义的dword数据的低字节[bx+2]存放到ax中        mov cx,dx                    ;把dx中的内容扔到cx中        mov es:[si],cx                    ;把cx中的内容放到[si]处        mov cx,ax                    ;把把低字节ax放到cx处        mov es:[si+4],cx                ;把cx中的内容放到[si+4]处        jcxz pb        mov dl,0a0h                    ;显存中一行有160个字节,所以存到cx中        mul dl                        ;因为一行有160个字节,所以乘以cx可以把光标定位到下一行        mov si,ax                    ; 把光标定位到下一行起始地址        add bx,4                    ;把ds中的光标定位到下一个地址        add si,4                    ;把es中的光标定位到下一个地址        jmp short pe        pb:        mov si,0        mov si,1Dh                    ;把光标定位到第一行的29字节处        mov dx,ds:[bx]                    ;把data段中定义的dword数据的高字节[bx]存放到dx中        mov ax,ds:[bx+4]                ;把data段中定义的dword数据的低字节[bx+2]存放到ax中        mov cx,dx                    ;把dx中的内容扔到cx中        mov es:[si],cx                    ;把cx中的内容放到[si]处        mov cx,ax                    ;把把低字节ax放到cx处        mov es:[si+4],cx                ;把cx中的内容放到[si+4]处        jcxz pm        mov dl,0a0h                    ;显存中一行有160个字节,所以存到cx中        mul dl                        ;因为一行有160个字节,所以乘以cx可以把光标定位到下一行        mov si,ax                    ; 把光标定位到下一行起始地址        add bx,4                    ;把ds中的光标定位到下一个地址        add si,4                    ;把es中的光标定位到下一个地址        jmp short pepm:        mov si,0        mov si,25h        mov cx,ds:[bx]        mov es:[si],cx        jcxz over        mov dl,0a0h        mul dl        mov si,ax        add bx,2        add si,2        jmp short pm        over:    pop bx        pop ax        pop bx        pop di        pop si        pop cx        retcode endsend start


[解决办法]


mov cl,[bx] 还是最好写明段寄存器。

其他可能还有点小问题。


这道题目是将这些数据计算下然后再显示吧?
王爽这道题目是考子程序的应用。把以前做的几个子程序直接调用,然后再多加点代码就行了。


把以前做的子程序直接赋值过来,包括那个标号,然后直接用CALL调用标号就行了。

先是用CALL调用以前计算工资什么的子程序
计算好了后不是会以字符串的形式存放在内存中吗?
这样不就简单了,另外一个子程序是根据的位置来显示某个字符串。


把指向的位置设置成刚刚计算好的数据段的位置就行了。
其余可能还要多加些代码


下面是我以前做的,楼主可以参考下整个思路。

好了不早了,该睡了,明天第一天去学车。。。


Assembly code
assume cs:code , ds:data , ss:stack; 数据段data segment        db '1975','1976','1977','1978','1979','1980','1981','1982','1983'    ;第一个偏移值:0        db '1984','1985','1986','1987','1988','1989','1990','1991','1992'        db '1993','1994','1995'        ;最后一个偏移值:53H(83D)        ;以上是表示21年的21个字符串         dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514        ;第一个偏移值:54H(84D)        dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000        ;最后一个偏移值:A7H(167D)        ;以上是表示21年公司总收入的21个dword型数据         dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226        ;第一个偏移值是:A8H(168D)        dw 11542,14430,15257,17800                                                    ;最后一个偏移值是:D2(210D)        ;以上是表示21年公司雇员人数的21个word型数据    dw 64 dup(?)        ; 因为最后转换成字符串的空间不够,所以需要再多申请这么多空间data ends; 栈段stack segment    db 256 dup (?)stack ends; 计算后的数据存放段table segment        db 21 dup ('year sunm ne ?? ')    dw 32 dup(?)        ; 因为最后转换成字符串的空间不够,所以需要再多申请这么多空间table ends; 代码段code segment start:    ; 设置栈段地址    mov ax , stack    mov ss , ax    mov sp , 256    ; 计算数据段中的数据(计算人均收入,也就是收入除以雇员数)    mov ax , data    mov ds , ax    mov bx , 0    call Calculate    ; 循环,将双字节的数据的整型数转换成字符型    mov bx , 0    mov si , 0            ; 设置字符串输出的首地址    mov cx , 21            ; 设置循环次数 again:     ; 复制年份到ds段    mov ax , es:[ bx ]    mov ds:[ si ] , ax    mov ax , es:[ bx + 2 ]    mov ds:[ si + 2 ] , ax    mov word ptr ds:[ si + 4 ] , 0    ; 存入0,表示间隔    add bx , 5            ; 因为只需跳过一个空格,空格占一个字节,再加上前面读取的4个字节    add si , 6    mov ax , es:[ bx ]        ; 获取公司总收入的dword型数据的低位    mov dx , es:[ bx + 2 ];        ; 获取公司总收入的dword型数据的高位    call dtoc            ; 调用子程序,将dword型数据转换成数字符串型,放到ds:si指定的位置    add bx , 5            ; 跳过已经读取的字节再加上一个空格    inc si                ; 如果去掉这个自增1,则存放他们之间的间隔0为一个字节,没有去掉这个自增就为一个字    mov ax , es:[ bx ]        ; 获取公司雇员人数的word型数据    mov dx , 0            ; 因为是word型数据,所以高位不需要,为0    call dtoc            ; 调用子程序,将dword型数据转换成数字符串型,放到ds:si指定的位置    add bx , 3            ; 跳过已经读取的字节再加上一个空格    inc si                ; 如果去掉这个自增1,则存放他们之间的间隔0为一个字节,没有去掉这个自增就为一个字    mov ax , es:[ bx ]        ; 获取公司雇员的人均收入    mov dx , 0            ; 因为是word型数据,所以高位不需要,为0    call dtoc            ; 调用子程序,将dword型数据转换成数字符串型,放到ds:si指定的位置    add bx , 3            ; 跳过已经读取的字节再加上一个空格    inc si                ; 如果去掉这个自增1,则存放他们之间的间隔0为一个字节,没有去掉这个自增就为一个字  loop again    ; 循环,用于显示所有的字符串    mov dh , 0            ; 第0行    mov dl , 2            ; 第2列    mov si , 0            ; 设置指向字符串首地址偏移量    mov cx , 22            ; 外循环共循环21次(因为第一次为了直接跳到循环处而一次性执行循环,所以需要多加一次循环)    jmp show_start            ; 跳到开始出,以便能直接使用loop循环一次性输出 show_again1:    push cx                ; 现场保护    mov cx , 4            ; 内循环共循环4次   show_again2:    push cx                ; 因为CX还要用来设置颜色,所以还要保护    mov ch , 0    mov cl , 01h            ; 设置颜色(蓝色)    call show_str    add si , 2            ; 加上间隔符,进行下一组字符串的输出    add dl , 10            ; 每输出一串字符列就空开几列    pop cx                ; 恢复内循环的循环次数值   loop show_again2    add dh , 1            ; 输出完一组就要换下一行    mov dl , 2            ; 输出完一组列就要归位    pop cx                ; 恢复外循环的循环次数值show_start: loop show_again1    ; 结束程序    mov ax , 4c00h    int 21h; 子程序; 计算数据段中的数据(计算平均收入,也就是收入除以雇员数); 入口参数:ds:bx为待计算的数据段; 出口参数:计算好后的数据将放在table数据段中,也可以用 es:0 来直接获取这个table数据段的首地址Calculate:        mov ax , table        mov es , ax            ;设置要写入数据的段寄存器        mov bp , 0            ;设置table段的偏移地址        mov di , 0            ;设置雇员数每次增加的值(因为与其他值相比只有雇员数是2字节,所以要做特殊处理)        mov cx , 21            ;设置循环的值为21次    again_1:                mov ax , ds:[bx]        ;复制年份的低字        mov es:[bp] , ax        mov ax , ds:[bx + 2]        ;复制年份的高字        mov es:[bp + 2] , ax        mov ax , ds:0A8H.[di]        ;复制雇员数(十进制168)        mov es:[bp + 0AH] , ax        ;加10是因为复制了2个字节,而且写入的时候要输入一个空格,                                    ;并且这个位置是在复制了4个字节后的再加5个字节的位置        mov ax , ds:54H.[bx]        ;复制收入的低字节(十进制84)        mov es:[bp + 5] , ax        mov dx , ds:54H.[bx + 2]    ;复制收入的高字节(十进制84)        mov es:[bp + 7] , dx        div word ptr ds:0A8H.[di]    ;因为除数是2个字节(16位)的,所以也用di(di每次循环增加2)        mov es:[bp + 0DH] , ax        ;复制算好的人均收入        add bp , 16        ;进行下一组写入        add di , 2        ;用于计算雇员数的值加2,因为他一次值复制了2个字节        add bx , 4        ;复制了一次后要加上4字节,以便下一次读出和计算    loop again_1  ret                    ; Calculate子程序返回;参数: (ax) = dword型数据的低16位;      (dx) = dword型数据的高16位;      (cx) = 除数;返回: (dx) = 结果的高16位;      (ax) = 结果的低16位;      (cx) = 余数divdw:  ;子程序定义开始        push ax        mov ax,dx        mov dx,0        div cx        mov bx,ax        pop ax        div cx        mov cx,dx        mov dx,bx        ret   ;子程序定义结束; 功能:将dword型数据转变为表示十进制数的字符,字符以0为结尾符; 参数:(ax) = dword型数据的低16位;      (dx) = dword型数据的高16位;      ds:si指向字符串的首地址; 返回:无  dtoc: push cx                ; 保护现场    push bx                ; 保护现场    push si                ; 保存用来输出结果的字符串的首地址    mov byte ptr ds:[ si ] , 0    ;先写入结束符(写在首位,以便配合栈结构)    inc si    mov cx , 1again_3:mov cx , 10            ; 做除数,每次都除以10,以便得到余数,从而求出每个位的值    call divdw            ; 调用除法子程序,因为这个除法子程序可以防止数据溢出    add cl , 30H            ;加上30H成为字符的ASCII码    mov ds:[ si ] , cl        ;存入到指定的数据段    ; 判断商的低位和高位是否都为0如果都为0,则表示结束    mov cx , 0    or cx , ax    or cx , dx    jcxz ok1    inc si    inc cx                ;因为loop会将cx减少1,所以要先加1    loop again_3 ok1:   mov byte ptr ds:[ si + 1 ] , 0    ;尾部也写入结束符    pop si                ; 取出用来输出结果的首地址    mov bx , si            ; bx用来做最后的数据存入,所以也是为输出结果的首地址    mov al , ds:[ si ]        ;从得到的第一个数据开始遍历    mov ah , 0            ;只要低位,高位归零    push ax                ;结束符先入栈    ;把得出的字符倒过来,因为求余得到的数是倒着的again_4:inc si    mov al , ds:[ si ]    mov ah , 0            ;只要低位,高位归零    mov cx , ax    jcxz ok2            ;已经全部临时存入栈中    push ax    inc cx                ;因为loop会将cx减少1,所以要先加1    loop again_4  ok2:  pop cx                ;从栈中取出,正好实现倒叙    mov ds:[ bx ] , cl        ;只要低位,高位归零    jcxz return    inc bx    inc cx                ;因为loop会将cx减少1,所以要先加1    loop ok2return: pop bx                ; 恢复现场    pop cx                ; 恢复现场    ret                ; 返回;子程序;功能:在指定的位置 , 用指定的颜色 , 显示一个用0结束的字符串;参数:(dh) = 行号(取值范围0~24) , (dl) = 列号(取值范围0~79);     (cl) = 颜色 , ds:si指向字符串首地址show_str:    push dx                ; 现场保护    mov ax , 000ah            ;转换成行需要乘以a(10)    mul dh                ;计算写入位置的行    add ax , 0b800h            ;B800是起始位置,所以加上规定的行数    add dl , dl            ;计算写入位置的列    mov dh , 0    mov es , ax            ;设置写入位置的寄存器    mov di , dx        mov al , cl            ;保存颜色    mov cx , 2    jmp first_start   again_2:    mov cl , ds:[si]        ;获取要显示的数据    mov ch , 0            ;不需要高位    jcxz ok                ;如果是0则返回(结束这个子程序)        mov es:[di] , cl        ;将字符写入    mov es:[di + 1] , al        ;写入颜色    add di , 2            ;指向下一个要写入的位置    inc si                ;指向下一个要读取字符的位置    mov cl , 2            ;again循环每次都成立first_start:   loop again_2ok:    pop dx                ; 恢复    ret                ;返回(结束)这个子程序code endsend start 

读书人网 >汇编语言

热点推荐