汇编语言-顺序结构程序设计

本文介绍了如何用汇编语言编写程序,包括转换小写字母为大写、十六位数的算术运算,以及段定义、段组使用和自定义堆栈的应用。还展示了如何处理双字数据的算术右移操作。
摘要由CSDN通过智能技术生成

目录

问题1:编写汇编语言源程序,实现从键盘键入单个小写字母,转换成对应的大写字母输出。

问题2:已知X,Y,Z为十六位带符号数,编写汇编语言源程序实现公式计算

问题3:段定义及段组定义伪指令的使用

问题4:自编程序,从键盘输入一个用$结尾的字符串,在屏幕上输出该字符串(不包括$)

问题5:自编程序:完成双字数据(如:87654321H)算术右移一个二进制位。


问题1:编写汇编语言源程序,实现从键盘键入单个小写字母,转换成对应的大写字母输出

实验代码如下所示:

;使用简化的段定义
.model small    ;定义存储模型时的段默认情况
.stack         ;指定堆栈段的大小,如果不指定,默认值为1kb
.data                                                           ;定义数据段
    string db 'Please input a Lowercase letter:',0dh,0ah,'$'
.code                      ;定义代码段
    start:
          mov ax,@data
          mov ds,ax
          lea dx,string
          mov ah,9
          int 21h

          mov ah, 1
          int 21h
          
          sub al, 20h
          mov dl, al
          mov ah, 2
          int 21h
          mov ah,4ch
          int 21h
end start  

运行程序,测试结果如下所示:


问题2:已知X,Y,Z为十六位带符号数,编写汇编语言源程序实现下列公式计算,并将除后的结果不仅存入Z中,也存入自定义的堆栈段中。

 

实现代码如下所示:

;已知XYZ为十六位带符号数,求((X+Y)*8-X)/2,将得到的结果存入Z和自定义的堆栈段
assume cs:code,ds:data,ss:stack
data segment
    array dw 1234H,4321H,?    ;分别为X,Y,Z的位置0000 0001,0002 0003,0004,0005
data ends
stack segment
    answer db 20 dup(?)

stack ends
code segment
    start:
          mov  ax,data
          mov  ds,ax
          mov  bx,stack
          mov  ss ,bx
          mov  bx,offset answer
          add  bx,4
          mov  sp,bx
        

          lea  si,array
          mov  ax,[si]
          mov  bx,[si+2]
          mov  di,si
          add  di,4                ;di存放Z的位置
          call calc

          push dx
          push ax                  ;将结果保存到自定义的堆栈段中
          mov  ax,4c00h
          int  21h
    calc: 
          push ax                  ;进入程序时ax = X, bx = Y
          add  ax,bx
          mov  bx,8H
          imul bx                  ;(X+Y)*8,此时高字节在dx,低字节在ax
         
          mov  cx,ax
          mov  bx,dx               ;将(X+Y)*8保存到bx,cx中
          pop  ax
          cwd                      ;将X转换为双字,放在dx,ax中
          sub  cx,ax
          sbb  bx,dx               ;减去进位
          mov  ax,cx
          mov  dx,bx               ;(X+Y)*8-X

          sar  dx,1                ;dx除以2,余数放入CF中,算术右移适合用来处理无符号运算
          rcr  ax,1                ;ax除以2,CF进ax中,余数进CF
          adc  ax,0                ;加上ax余数

          mov  [di],ax
          mov  [di+2],dx           ;小端存储,低字节放低地址,高字节放高地址,结果位4c3a
         
          ret
        
code ends
end start

使用debug观察运行结果如下所示:


问题3:段定义及段组定义伪指令的使用

实现代码如下所示:

data1 segment  word  'data'
    const1 dw 100
    const2 db -12H
data1 ends
data2 segment  word  'data'
    var1  dw ?
data2 ends
datagroup  group  data1,data2
code segment
          assume cs:code,  ds:datagroup
    start:
          mov    ax, datagroup
          mov    ds, ax
          mov    al, byte ptr const1+1     ;101
          mov    var1, ax
          mov    ax, 4c00h
          int    21h
code ends
end   start

(1)、编辑,编译,连接,生成LST文件,运行该程序获得如下结果:

(2)、使用type命令查看生成的.LST文件内容,如下所示:

可以观察到各个变量const1,const2,var1,标号start,文件名filename:4-3其中:

const1的type类型为word,偏移地址为0000,属于数据段data1

const2的类型为byte,偏移地址为0002,属于数据段data1

var1的类型为word,偏移地址为0000,属于数据段data2

start的类型为near,说明该标号是在本段内部引用的,偏移地址为0000,属于代码段code,使用debug追踪调试,可以观察到便变量const1和const2以及var1修改之后的值

const1上的值为100,即0064const2上的值为-12byte类型)即为EEmov ax,const1+1const1+10001,而ax为字单元,所以从0002-0001取一个字数据即EE00赋值给ax寄存器所以(ax= 00EE,再将ax中的内容赋值给变量var1,所以var1中的值为00EE。

(3)data1段和data2段的起始字节的物理地址显然是不相同的,两个段使用段组定义伪操作,共用同一个数据段段,其偏移地址必然不相同,添加指令,获取两端首字节的段地址和偏移地址。添加指令如下:

mov    ax,seg const1
mov    bx,seg var1
mov    dx,offset const1
mov    cx,offset var1

Debug追踪调试,可以观察到data1var1的段地址相同,均为076C,而偏移地址不同,分别为00000004,与上一题的分析符合一致,两者的物理地址不相同,并且两个数据段的存储位置存在一个字节的间隔,而代码段CS的段地址为076D,显然与两个数据段之间的存储位置是有间隔的。

(4)、之前的程序中(ax)的值修改为EE00al中的值为00

ax修改为al后,由于const1是字数据,而al是字节类型,显然会报错.修改该指令的源操作数

的类型为字节型数据即可,修改指令如下所示:

mov    al, byte ptr const1+1

得到al的正确结果00

问题4:自编程序,从键盘输入一个用$结尾的字符串,在屏幕上输出该字符串(不包括$)

assume cs:code,ds:data
data segment
       output db 'Enter your string: $'
       input  db 0dh,0ah,'Your input is'
       string db 30 DUP('1')
data ends
code segment
       start:
             mov ax,data
             mov ds,ax

             lea dx,output
             mov ah,9h
             int 21h

             lea dx,string
             mov ah,0ah
             int 21h
             
             mov ax, 203AH
             mov word ptr string,ax       ;将dx和dx+1中的值覆盖

             lea dx,input
             mov ah,9
             int 21h

             mov ax,4c00h
             int 21h

code ends
end start

运行结果如下所示:


题目五:自编程序:完成双字数据(如:87654321H)算术右移一个二进制位。

对一个双字数据进行算术右移,最低位进入CF标志寄存器,最高位保持不变

因此我们将该数据分别存放在dx(高16位)和ax(低16位),然后对dx进行算术右移一位,再对ax进行带进位循环右移一位即可,高16位的最低一位进入CFCF再进入低十六位的最高位,低十六位的最低一位进入CF寄存器即可完成双字数据的算术右移,实验程序如下所示:

assume cs:code,ds:data
data segment
    num  dd 87654321H
data ends
code segment
    start:
          mov ax,data
          mov ds,ax
          lea si,num
          mov ax,[si]
          mov dx,[si+2]
          sar dx,1
          rcr ax,1
          mov ax,4c00h
          int 21h

code ends
end start

借用计算机求得算术右移的结果应当为87654321/2+10000000 = C3B2 A190

调试源程序得到如下结果:

右移之前(dx)= 8765,(ax)= 4321.CF = 0

右移之后,(dx)= C3B2 ,(ax) = A190,CF = 1

即双字右移后的结果位C3B2 A190,与预期结果一致

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值