输出 BCD 码

实验内容:

在内存一个字节的单元中存放两位 BCD 码(8421 码),通过编程实现将这两位 BCD 码转为 ASCII 码输出。

思路:

数字的 BCD 码与 ASCII 码的对应关系如下:

数字

0

1

2

3

4

5

6

7

8

9

BCD 码(十六进制)

0

1

2

3

4

5

6

7

8

9

ASCII 码(十六进制)

30

31

32

33

34

35

36

37

38

39

通过观察发现,只需将 BCD 码的值与 0x30 做或运算,即可转换为 ASCII 码。

[org    0x7c00]

start:
    xor    bh,bh          ; 将 bh 清空
    mov    bl,[bcd_num]   ; 取出内存中的 BCD 码送入 bl
    shl    bx,4           ; bx 中的 BCD 码左移 4 位,高位数字移入 bh 的低位,低位数字移入 bl 的高位
    shr    bl,4           ; bl 中的 BCD 码右移 4 位,低位数字移入 bl 的低位
    or    bx,0x3030      ; bh 和 bl 同时与 0x30 做或运算

    mov    al,bh         ; 输出高位
    mov    ah,0x0e       ; 输出一个字符
    int    0x10          ; 调用 BIOS 中断

    mov    al,bl         ; 输出低位
    mov    ah,0x0e       ; 输出一个字符
    int    0x10          ; 调用 BIOS 中断

fin:
    hlt
    jmp    fin

bcd_num:
    db    0x42     ; 存放 BCD 码 42

signature:
    %if    $-$$>510
        %fatal    "stage1 code exceed 512 bytes."
    %endif

    times    510-($-$$) \
        db    0
    db    0x55,0xaa

读盘

BIOS 只会将启动介质第一个扇区的内容读入内存 0x7c00-0x7bff 处,如果程序大于一个扇区,后面的内容就要通过 BIOS 中断读入内存。

实验内容:

实验内容同上,但两位 BCD 码存放在第二扇区。

思路:

BIOS 中断 INT 13H,AH=02H 从驱动器中读扇区。

参数

  • AH 02h

  • AL Sectors To Read Count

  • CH Cylinder

  • CL Sector

  • DH Head

  • DL Drive

  • ES:BX Buffer Address Pointer

结果

  • CF Set On Error, Clear If No Error

  • AH Return Code

  • AL Actual Sectors Read Count

DL 中存放的是设备号。由于运行 QEMU 时,命令行参数中指定了 media=disk,是硬盘,编号从 0x80 开始,第一块硬盘的设备号为 0x80。若是软盘,则从 0 开始。

根据内存分布图可知,0x7e00-0x7fff 这 512 字节的内容是空闲的,可以存放第二扇区。

参考资料:

Bochs 调试方法

附录

Makefile

基本函数实现

扬声器发声

beep

Last updated