• 西电计组II 实验二


    西电计组II 实验二

    8086汇编实验二: 数制转换

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

    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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    考虑如何用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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    因此可以包装一个函数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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5

    以上两个就足够了

    下面考虑将一个最多五位整数的字符串转化为一个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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    任务一:数制转换

    输入一个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
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344
    • 345
    • 346
    • 347
    • 348
    • 349
    • 350
    • 351
    • 352
    • 353
    • 354
    • 355
    • 356
    • 357
    • 358
    • 359
    • 360
    • 361

    任务二:统计数字个数

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

     
    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
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
  • 相关阅读:
    超分辨率技术在实时音视频领域的研究与实践
    android自定义View: 饼状图绘制(四)
    RabbitMQ开启消息发送确认和消费手动确认
    Arduino追光小车
    HCIA实验(07)
    网页前端设计-作业四(HTML5)
    2023_11_6 每日半小时 SQL 刷题
    通信互联网运营、高速公路都在用的吹缆机---- 高性能拉缆机 提高工作效率 保护光缆防护层 液压型吹缆机
    HttpOnly Cookie 标志
    pytest简明教程
  • 原文地址:https://blog.csdn.net/qq_26131031/article/details/127944309