西电计组II 实验二

西电计组II 实验二

8086汇编实验二: 数制转换

重复从键盘输入不超过5位的十进制数,按回车键结束输入;
将该十进制数转换成二进制数;结果以2进制数的形式显示在屏幕上;
如果输入非数字字符,则报告出错信息,重新输入;
直到输入“Q”或‘q’时程序运行结束。
键盘输入一字符串,以空格结束,统计其中数字字符的个数,在屏幕显示

sum维护在BX寄存器中

首先使用int 21H软中断AH=0AH入口,输入一串字符串,放到buffer中

buffer[0]也需要在中断之前指定一下buffer缓冲区的大小

buffer[1]在中断获取输入返回之后,存放的是实际上输入的字符个数

我们希望输入5位十进制整数,因此首先检查buffer[1],如果等于0或者大于5都要报错,然后程序回到最初状态,重新接受输入

buffer[2]开始就是实际获取到的输入了,比如输入12345,那么就有

buffer[0]sizeof(buffer)
buffer[1]strlen(buffer)
buffer[2]‘1’
buffer[3]‘2’
buffer[4]‘3’

显然buffer[2]的权位最高,越往后越低,伪代码表示为

for(i=2;i<=len;++i){
	if(buffer[i]>='0'&&buffer[i]<='9'){
		sum=sum*10+(buffer[i]-'0');
	}
	else{
		//输入非法,报错,重来
	}
}
binary(sum)

考虑如何用8086汇编实现之

首先这个十进制数最大5位,而一个AX寄存器最长是 2 16 = 65536 2^{16}=65536 216=65536,

也就是说5位的十进制数有可能用一个寄存器放不下

如果只用AX,则达到65535之后就发生整数上溢,mod 65536截断

考虑用DX:AX一起作为sum

假设故意找茬输入了65536

前四个只是用AX可以正常计算到6553,如果继续之前的套路计算,会有6553*10+6=65536

然后mod 65536=0,算了个寂寞吧

应该怎么算?就是用8086实现32位整数,即int的加减乘除运算

首先考虑加法运算

32位加法

8086提供了两种加法指令,ADD和ADC

前者不考虑进位标志CF,后者要考虑

也就是ADD A,B相当于A+B->A

ADC A,B相当于A+B+CF->A

这样的话一个32位数可以分两次运算

mov ax,first_low
mov bx,second_low
add ax,bx	;ax+bx->ax,此时考虑进位
mov dx,first_high
mov di,second_high
adc dx,di	;dx+bx+cf->dx

因此可以包装一个函数op_add(first in DX:AX,second in DI:BX)

op_add proc near
	;first in DX:AX
	;second in DI:BX
	add AX,BX
	adc DX,DI
	ret
op_add endp

32位乘法

本次程序中,最多使用到两个16位数的乘法,MUL可以胜任工作

MUL BX的被乘数隐含在AX中,两个16位数相乘,乘积最多是32位的,存放于DX:AX中

op_mul proc near
	;a*b, factors use AX and BX
    mul BX
    ret	;result in DX:AX 
op_mul endp

以上两个就足够了

下面考虑将一个最多五位整数的字符串转化为一个DX:AX这样存放的数值

修改一下input函数,CX返回实际输入字符数,AX返回字符串首地址,也就是说AX之前指向buffer,现在指向buffer+2

这样

AX=字符串基地址,存放的是十进制数的最高位

CX=字符串长度

atoi proc near
	push si
	loop0:
	mov si,ax;ax要进行计算,si承担其责任
	mov ax,0
	mov dx,0	;sum=0->DX:AX
	mov bx,10
	call op_mul
	mov bh,0
	mov bl,ds:[si]
	mov di,0
	call op_add
	dec cx
	inc si
	cmp cx,0
	jz fini
	jmp loop0
	
	
	fini:
	pop si
	ret
atoi endp

任务一:数制转换

输入一个5位以内的整数,输出其二进制表示,

DSEG SEGMENT
    dbg  DB 'debugger, actived!' ,0DH,0AH,24H
    next_row   DB 0DH,0AH,24H
    buffer     DB 0100H dup('$')
    hint       db 'please input an decimal within 5 digit number > $'
    STUID      DB 'please input your id >','$'
    STUNAME    DB 'please input your name >','$'
    cmdprompt  DB 'please input an alpha to get its ascii code, q to quit >','$'
    badinput   DB 'input length should in [1,5] ,please re input $'
DSEG ENDS

SSEG SEGMENT PARA STACK
         DW 256 DUP(?)
SSEG ENDS

CSEG SEGMENT
                  ASSUME CS:CSEG,DS:DSEG


    ;调用约定:需要打印的字符->al
putchar proc
                  push   dx
                  push   ax
                  mov    ah,02h
                  mov    dl,al
                  int    21h
                  pop    ax
                  pop    dx
                  ret
putchar endp

    ;调用约定:输入字符用al返回
getchar proc near
                  mov    ah,01h
                  mov    al,0
                  int    21H
                  retn

getchar endp



    ;16进制打印一个字节,调用约定:
hex PROC near

                  push   ax
                  push   dx
                  mov    dx,ax
                  mov    ch, 4
        
    L1:           
                  mov    cl, 4
                  rol    dx, cl
                  mov    al,dl
                  and    al,0FH
                  add    al,30h
                  cmp    al,3ah
                  jl     printit
                  add    al,7h
    printit:      
                  call   putchar
                  dec    ch
                  jnz    L1
                  pop    dx
                  pop    ax
                  ret
hex ENDP
        
        

    ;二进制形式的输出,入口参数为ax
binary proc
                  push   bx                        ;数据入栈,保留数值
                  push   dx
 
                  mov    dh,0                      ;用于计数,总共16次
	
    binaryagain:  
                  cmp    dh,16
                  je     binaryover                ;输出结束,到达函数末端
                  rol    ax,1                      ;移动一位
                  mov    bx,ax                     ;数值保留
                  and    ax,0001h                  ;剥离出最后一位
                  mov    dl,al                     ;用于输出
                  add    dl,48
                  mov    ah,2
                  int    21h
                  inc    dh                        ;计数加一
                  mov    ax,bx                     ;数值恢复
                  jmp    binaryagain               ;再来一次
	
    binaryover:   
                  pop    dx                        ;数据出栈,数值还原
                  pop    bx
                  ret
binary endp


    ;调用约定:ax指定一个buffer的基地址,用于获取一个字符串
print proc near
                  push   bx
                  push   cx
                  push   dx

                  mov    dx,ax
                  mov    ah,09H
                  mov    al,00H
                  int    21H

                  pop    dx
                  pop    cx
                  pop    bx
                  ret
print endp


    ;调用约定:ax指定一个buffer的基地址,用于获取一个字符串
println proc near
                  call   print
                  mov    al,0Dh
                  call   putchar
                  mov    al,0DH
                  call   putchar
                  ret
println endp

newline proc near
                  push   ax
                  lea    ax,next_row
                  call   print
                  pop    ax
                  ret
newline endp

    ;AX存放目的地址,结束时CX返回输入字符个数
input proc near
                  push   BX
    ;     push   cx
    ;     push   di
    ;     push   ax
    ;     MOV    CX, 0ffh
    ;     mov    DI, ax
    ;     mov    al,'$'
    ;     REPZ   STOSB

    ;     pop    ax

                  MOV    DX,AX
                  MOV    BX,DX
                  MOV    byte ptr DS:[BX], 0ffh
    ;     mov    [DX],BL
                  mov    ah,0ah                    ;将0ah放入ah
                  mov    al,0
                  int    21h                       ;输入字符串功能调用
                  mov    CX,0
                  mov    CL,DS:[BX+1]
                  lea    AX,DS:[BX+2]
                  pop    BX
                  ret
input endp
        
        
circle proc near
    rolling:      
                  lea    ax,cmdprompt
                  call   println
                  call   getchar
                  cmp    al,'q'
                  jz     fini
                  mov    ah,0
                  call   newline
                  call   hex
                  call   newline
                  jmp    rolling
    fini:         
                  retn

circle endp


    ;调用约定:ax存放基地址,cx存放长度,bl存放目标字符
memset proc near
                  push   di
                  mov    di,ax
    memset_circle:
                  cmp    cx,0
                  jz     memset_fini
                  mov    ds:[di],bl
                  inc    di
                  dec    cx
                  jmp    memset_circle

    memset_fini:  
                  pop    di
                  ret
memset endp



op_mul proc near
    ;a*b, factors use AX and BX
                  mul    BX
                  ret                              ;result in DX:AX
op_mul endp


op_add proc near
    ;first in DX:AX
    ;second in DI:BX
                  add    AX,BX
                  adc    DX,DI
                  ret
op_add endp


debugger proc near
                  push   ax
                  lea    ax,dbg
                  call   print
                  call   newline
                  pop    ax
                  ret
debugger endp



    ;检查一个字符是否是数字,BL传递ascii值,如果是则bp为1,否则为0
isdigit proc near
                  cmp    bl,'9'
                  jz     flagon
                  cmp    bl,'8'
                  jz     flagon
                  cmp    bl,'7'
                  jz     flagon
                  cmp    bl,'6'
                  jz     flagon
                  cmp    bl,'5'
                  jz     flagon
                  cmp    bl,'4'
                  jz     flagon
                  cmp    bl,'3'
                  jz     flagon
                  cmp    bl,'2'
                  jz     flagon
                  cmp    bl,'1'
                  jz     flagon
                  cmp    bl,'0'
                  jz     flagon
                  cmp    bl,'q'
                  jz     flagfail
                  mov    bp,0
                  ret



    flagon:       
                  mov    bp,1
                  ret
    flagfail:     
                  mov    bp,-1
                  ret
isdigit endp



    ;buffer+2 in AX,length in CX
atoi proc near
                  mov    si,ax
                  mov    di,0
                  mov    ax,0
                  mov    bx,0
                  mov    dx,0
    shift:        
    
                  cmp    cx,0
                  jz     atoi_fini
    ;   call   debugger
                  mov    bx,10
                  call   op_mul
                  mov    bl,[si]
                  call   isdigit
                  cmp    bp,0
                  jz     atoi_fail
                  cmp    bp,-1
                  jz     atoi_exit
     


                  sub    bl,'0'
                  call   op_add
                  inc    si
                  dec    cx
                  jmp    shift
    atoi_fini:    
                  mov    bp,1
                  ret
    atoi_exit:    
                  call   exit

    atoi_fail:    
                  mov    bp,0
                  ret
atoi endp



exit proc near
                  mov    ah,4Ch
                  mov    al,0
                  int    21h
exit endp
       
    BEGIN:        
                  MOV    AX,DSEG
                  MOV    DS,AX

    loopinput:    
                  call   newline
                  lea    AX,hint
                  call   print


                  call   newline
                  lea    AX,buffer
                  mov    cx,0ffh
                  mov    bl,'$'
                  call   memset
                  lea    AX,buffer
                  call   input

    ;首先判断输入长度是否合法,要大于0小于6
                  cmp    cx,6
                  jnc    loopinput
                  cmp    cx,0
                  jz     loopinput
                

                ;   call   debugger
                  call   atoi
                  cmp    bp,0
                  jz     loopinput

                  xchg   ax,dx;先打印高位的dx,然后才是低位的ax
                  call   binary
                  
                  mov    ax,dx
  
                  call   binary
                  call   newline
                  jmp    loopinput


    main_fini:    

                  call debugger

                  call   exit
CSEG ENDS
        END  BEGIN


任务二:统计数字个数

输入一个字符串,统计其中的数字的个数

 
assume cs:code,ds:data,ss:mystack
 
data segment
        hint     db 'input a string then the program will tell the number of digits>$'
        buffer   DB 0100H dup('$')
        debugger db 'debugging',10,13,'$'
        next_row DB 0DH,0AH,24H
data ends
mystack segment stack
                db 32 dup(?)
mystack ends
 
code segment
newline proc near
                   push ax
                   lea  ax,next_row
                   call print
                   pop  ax
                   ret
newline endp

        ;调用约定:需要打印的字符->al
putchar proc
                   push dx
                   push ax
                   mov  ah,02h
                   mov  dl,al
                   int  21h
                   pop  ax
                   pop  dx
                   ret
putchar endp

        ;AX存放目的地址,结束时CX返回输入字符个数
input proc near
                   push BX
        ;     push   cx
        ;     push   di
        ;     push   ax
        ;     MOV    CX, 0ffh
        ;     mov    DI, ax
        ;     mov    al,'$'
        ;     REPZ   STOSB

        ;     pop    ax

                   MOV  DX,AX
                   MOV  BX,DX
                   MOV  byte ptr DS:[BX], 0ffh
        ;     mov    [DX],BL
                   mov  ah,0ah                        ;将0ah放入ah
                   mov  al,0
                   int  21h                           ;输入字符串功能调用
                   pop  BX
                   ret
input endp
        ;调用约定:ax指定一个buffer的基地址,用于获取一个字符串
print proc near
                   push bx
                   push cx
                   push dx

                   mov  dx,ax
                   mov  ah,09H
                   mov  al,00H
                   int  21H

                   pop  dx
                   pop  cx
                   pop  bx
                   ret
print endp

hello proc near
                   push ax
                   lea  ax,buffer
                   call print
                   call newline
                   pop  ax
                   ret
hello endp
isdigit proc near
                   cmp  bl,'9'
                   jz   flagon
                   cmp  bl,'8'
                   jz   flagon
                   cmp  bl,'7'
                   jz   flagon
                   cmp  bl,'6'
                   jz   flagon
                   cmp  bl,'5'
                   jz   flagon
                   cmp  bl,'4'
                   jz   flagon
                   cmp  bl,'3'
                   jz   flagon
                   cmp  bl,'2'
                   jz   flagon
                   cmp  bl,'1'
                   jz   flagon
                   cmp  bl,'0'
                   jz   flagon

                   jmp  flagoff

        flagon:    
                   mov  bp,1
                   ret
        flagoff:   
                   mov  bp,0
                   ret
isdigit endp

exit proc near
                   mov  ah,4ch
                   mov  al,0
                   int  21h
exit endp


        ;buffer+2 in AX,length in CX,result in AX
count proc near
                   push di
                   mov  di,ax
                   mov  ax,0
        loop_count:
                   mov  bl,[di]
                   call isdigit
                   cmp  bp,1
                   jnz  bottom
        add_count: 
                   inc  ax
        bottom:    
                   dec  cx
                   inc  di
                   cmp  cx,0
                   jnz  loop_count

                   pop  di
                   ret
count endp


        ;16进制打印一个字节,调用约定:
hex PROC near

                   push ax
                   push dx
                   mov  dx,ax
                   mov  ch, 4
        
        L1:        
                   mov  cl, 4
                   rol  dx, cl
                   mov  al,dl
                   and  al,0FH
                   add  al,30h
                   cmp  al,3ah
                   jl   printit
                   add  al,7h
        printit:   
                   call putchar
                   dec  ch
                   jnz  L1
                   pop  dx
                   pop  ax
                   ret
hex ENDP
        start:     
                   mov  ax,data
                   mov  ds,ax
                   lea  ax,hint
                   call print
                   lea  ax,buffer
                   call input
                   lea  ax,[buffer+2]
                   call count
                   call newline
                   call hex

	
                   call exit

code ends
end start

  • 6
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

灰球球

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值