鱼C论坛

 找回密码
 立即注册
查看: 2222|回复: 7

[汇编作业] 编写程序,读两个扇区,显示到屏幕Hello world

[复制链接]
发表于 2021-11-23 10:22:47 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
将“ hello”和 world”两个字符串分别写到第 100和 101扇区,编写程序 test13-3.asm读取这二个扇区,并将两个字符串显示到屏幕上。程序运行后如图:

                               
登录/注册后可看大图



ps:有没有学汇编的一起来交流一下!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-11-23 11:07:02 | 显示全部楼层
        绝对写磁盘扇区是一件非常危险事情,必须十分慎重,闹不好,会破坏磁盘关键数据,例如,FAT 扇区、目录扇区等内容,从而对磁盘的安全健康状态造成不可逆的损害。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-11-23 20:05:23 | 显示全部楼层
jackz007 发表于 2021-11-23 11:07
绝对写磁盘扇区是一件非常危险事情,必须十分慎重,闹不好,会破坏磁盘关键数据,例如,FAT 扇区、 ...

在Ubuntu构建的虚拟硬盘,和虚拟机,这只是学习所需。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-11-23 20:46:24 | 显示全部楼层
read.s
  1.     .code16
  2.     .globl  _start
  3. _start:
  4.     lgdtw   gdtr + 0x7c00

  5.     # 打开A20地址线
  6.     inb     $0x92, %al
  7.     orb     $0x02, %al
  8.     outb    %al, $0x92

  9.     cli         # bootsect不打算建立保护模式下的中断机制

  10.     # 进入保护模式
  11.     movl    %cr0, %eax
  12.     orl     $1, %eax
  13.     movl    %eax, %cr0
  14.     ljmpl   $8, $flush + 0x7c00

  15.     .code32
  16. flush:
  17.     movw    $16, %ax
  18.     movw    %ax, %ds
  19.     movw    %ax, %es
  20.     movw    %ax, %fs
  21.     movw    %ax, %gs
  22.     movw    %ax, %ss
  23.     movl    $0xa0000, %esp

  24.     movl    %esp, %ebp
  25.     subl    $512, %esp
  26.     subl    $8, %esp

  27.     leal    -512(%ebp), %eax
  28.     movl    $100, %ebx
  29.     movl    %eax, (%esp)
  30.     movl    %ebx, 4(%esp)
  31.     calll   read_sect

  32.     leal    -512(%ebp), %ebx
  33.     movb    (%ebx), %al
  34.     movb    %al, 0xb8000
  35.     movb    1(%ebx), %al
  36.     movb    %al, 0xb8002
  37.     movb    2(%ebx), %al
  38.     movb    %al, 0xb8004
  39.     movb    3(%ebx), %al
  40.     movb    %al, 0xb8006
  41.     movb    4(%ebx), %al
  42.     movb    %al, 0xb8008

  43.     leal    -512(%ebp), %eax
  44.     movl    $101, %ebx
  45.     movl    %eax, (%esp)
  46.     movl    %ebx, 4(%esp)
  47.     calll   read_sect

  48.     leal    -512(%ebp), %ebx
  49.     movb    (%ebx), %al
  50.     movb    %al, 0xb80a0
  51.     movb    1(%ebx), %al
  52.     movb    %al, 0xb80a2
  53.     movb    2(%ebx), %al
  54.     movb    %al, 0xb80a4
  55.     movb    3(%ebx), %al
  56.     movb    %al, 0xb80a6
  57.     movb    4(%ebx), %al
  58.     movb    %al, 0xb80a8

  59. 1:
  60.     hlt
  61.     jmp 1b

  62. #void read_sect(uint8_t *buf, size_t start_sect);
  63. read_sect:
  64.     pushl   %ebp
  65.     movl    %esp, %ebp
  66.     pushl   %edi

  67.     # 读取1个扇区
  68.     movb    $1, %al
  69.     movl    $0x1f2, %edx
  70.     outb    %al, %dx

  71.     # 下面发送逻辑扇区号
  72.     # 0~7
  73.     movl    12(%ebp), %ecx
  74.     movl    %ecx, %eax
  75.     movl    $0x1f3, %edx
  76.     outb    %al, %dx

  77.     # 8~15
  78.     movl    %ecx, %eax
  79.     shrl    $8, %eax
  80.     movl    $0x1f4, %edx
  81.     outb    %al, %dx

  82.     # 16~23
  83.     movl    %ecx, %eax
  84.     shrl    $16, %eax
  85.     movl    $0x1f5, %edx
  86.     outb    %al, %dx

  87.     # LBA28模式, 主盘
  88.     # LBA地址24~27
  89.     movl    %ecx, %eax
  90.     shrl    $24, %eax
  91.     andl    $0x0f, %eax
  92.     orl     $0xe0, %eax
  93.     movl    $0x1f6, %edx
  94.     outb    %al, %dx

  95.     # 发送读命令
  96.     movb    $0x20, %al
  97.     movl    $0x1f7, %edx
  98.     outb    %al, %dx

  99.     # 等待硬盘准备好
  100. .L1:
  101.     inb     %dx, %al
  102.     andb    $0x88, %al
  103.     cmpb    $0x08, %al
  104.     jne     .L1

  105.     # 从硬盘读取数据
  106.     movl    8(%ebp), %edi
  107.     movl    $256, %ecx
  108.     movl    $0x1f0, %edx
  109.     cld
  110.     rep     insw

  111.     popl    %edi
  112.     popl    %ebp
  113.     retl

  114.     .align  4
  115. gdt:
  116.     # 空描述符
  117.     .int    0, 0

  118.     # 代码段描述符
  119.     # 段基地址: 0
  120.     # 段界限:   4GB
  121.     .int    0x0000ffff, 0x00cf9a00

  122.     # 数据段描述符
  123.     # 段基地址: 0
  124.     # 段界限:   4GB
  125.     .int    0x0000ffff, 0x00cf9200
  126. gdtr:
  127.     .short  (. - gdt - 1)
  128.     .int    (gdt + 0x7c00)
复制代码


write.s
  1.     .code16
  2.     .globl  _start
  3. _start:
  4.     lgdtw   gdtr + 0x7c00

  5.     # 打开A20地址线
  6.     inb     $0x92, %al
  7.     orb     $0x02, %al
  8.     outb    %al, $0x92

  9.     cli         # bootsect不打算建立保护模式下的中断机制

  10.     # 进入保护模式
  11.     movl    %cr0, %eax
  12.     orl     $1, %eax
  13.     movl    %eax, %cr0
  14.     ljmpl   $8, $flush + 0x7c00

  15.     .code32
  16. flush:
  17.     movw    $16, %ax
  18.     movw    %ax, %ds
  19.     movw    %ax, %es
  20.     movw    %ax, %fs
  21.     movw    %ax, %gs
  22.     movw    %ax, %ss
  23.     movl    $0xa0000, %esp

  24.     movl    %esp, %ebp
  25.     subl    $512, %esp
  26.     subl    $8, %esp

  27.     leal    -512(%ebp), %ebx
  28.     movb    $'h', (%ebx)
  29.     movb    $'e', 1(%ebx)
  30.     movb    $'l', 2(%ebx)
  31.     movb    $'l', 3(%ebx)
  32.     movb    $'o', 4(%ebx)

  33.     leal    -512(%ebp), %eax
  34.     movl    $100, %ebx
  35.     movl    %eax, (%esp)
  36.     movl    %ebx, 4(%esp)
  37.     calll   write_sect

  38.     leal    -512(%ebp), %ebx
  39.     movb    $'w', (%ebx)
  40.     movb    $'o', 1(%ebx)
  41.     movb    $'r', 2(%ebx)
  42.     movb    $'l', 3(%ebx)
  43.     movb    $'d', 4(%ebx)

  44.     leal    -512(%ebp), %eax
  45.     movl    $101, %ebx
  46.     movl    %eax, (%esp)
  47.     movl    %ebx, 4(%esp)
  48.     calll   write_sect

  49. 1:
  50.     hlt
  51.     jmp 1b

  52. #void write_sect(const uint8_t *buf, size_t start_sect);
  53. write_sect:
  54.     pushl   %ebp
  55.     movl    %esp, %ebp
  56.     pushl   %esi

  57.     # 写入1个扇区
  58.     movb    $1, %al
  59.     movl    $0x1f2, %edx
  60.     outb    %al, %dx

  61.     # 下面发送逻辑扇区号
  62.     # 0~7
  63.     movl    12(%ebp), %ecx
  64.     movl    %ecx, %eax
  65.     movl    $0x1f3, %edx
  66.     outb    %al, %dx

  67.     # 8~15
  68.     movl    %ecx, %eax
  69.     shrl    $8, %eax
  70.     movl    $0x1f4, %edx
  71.     outb    %al, %dx

  72.     # 16~23
  73.     movl    %ecx, %eax
  74.     shrl    $16, %eax
  75.     movl    $0x1f5, %edx
  76.     outb    %al, %dx

  77.     # LBA28模式, 主盘
  78.     # LBA地址24~27
  79.     movl    %ecx, %eax
  80.     shrl    $24, %eax
  81.     andl    $0x0f, %eax
  82.     orl     $0xe0, %eax
  83.     movl    $0x1f6, %edx
  84.     outb    %al, %dx

  85.     # 发送写命令
  86.     movb    $0x30, %al
  87.     movl    $0x1f7, %edx
  88.     outb    %al, %dx

  89.     # 等待硬盘准备好
  90. .L1:
  91.     inb     %dx, %al
  92.     andb    $0x88, %al
  93.     cmpb    $0x08, %al
  94.     jne     .L1

  95.     # 把数据写入硬盘
  96.     movl    8(%ebp), %esi
  97.     movl    $256, %ecx
  98.     movl    $0x1f0, %edx
  99.     cld
  100.     rep     outsw

  101.     popl    %esi
  102.     popl    %ebp
  103.     retl

  104.     .align  4
  105. gdt:
  106.     # 空描述符
  107.     .int    0, 0

  108.     # 代码段描述符
  109.     # 段基地址: 0
  110.     # 段界限:   4GB
  111.     .int    0x0000ffff, 0x00cf9a00

  112.     # 数据段描述符
  113.     # 段基地址: 0
  114.     # 段界限:   4GB
  115.     .int    0x0000ffff, 0x00cf9200
  116. gdtr:
  117.     .short  (. - gdt - 1)
  118.     .int    (gdt + 0x7c00)
复制代码


1.bmp
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 2 反对 0

使用道具 举报

 楼主| 发表于 2021-11-24 21:34:06 | 显示全部楼层
                        ;文件名:port_hd_hello.asm
                        ;功能:1.读取硬盘逻辑扇区号100处的1个扇区到物理内存0x10000处
                        ;      2.并显示扇区开头的‘hello'
                        ;           3.MBR程序
                        ;目的:练习对硬盘的端口访问
                        ;说明:本末终始2020-11-24,参考李忠c08_mbr.asm
                        app_lba_start equ 100                ;'hello'在第100扇区(LBA)
SECTION hello align=16 vstart=0x7c00
                        ;设置堆栈段和栈指令
                        xor ax,ax
                        mov ss,ax
                        mov sp,ax
                       
                        ;设置DS和ES
                        mov ax,0x1000                                ;0x10000的段地址,接收扇区来的数据
                        mov ds,ax
                        mov es,ax
                       
                        ;调用call及参数设置:扇区号和装载内存偏移地址
                        xor di,di
                        mov si,app_lba_start                ;di:si:逻辑扇区号100
                        xor bx,bx                                        ;装载扇区的内存区偏移地址0
                        call read_hard_disk_0                ;从硬盘读取一个逻辑扇区,到DS:BX(内存0x10000)。引自李忠c08_mbr.asm
                       
                        ;显示'hello'5个字符到0xb8000
                        mov ax,0xb800
                        mov es,ax
                        xor si,si
                        xor di,di
                        mov cx,5                                        ;显示'hello'5个字符
disp:
                        mov al,[si]
                        mov ah,0x07
                        mov [es:di],ax
                        inc si
                        inc di
                        inc di
                        loop disp
                       
                        jmp $                                                ;程序结束
                       
;-----------------------------------------------------------------------------

read_hard_disk_0:                        ;从硬盘读取一个逻辑扇区
                                         ;输入:DI:SI=起始逻辑扇区号
                                         ;      DS:BX=目标缓冲区地址
                         push ax                                                ;过程中使用,端口数据
                         push bx                                                ;过程中使用,退出后需恢复
                         push cx                                                ;过程中使用,计数
                         push dx                                                ;过程中使用,端口号
                  
                         mov dx,0x1f2
                         mov al,1
                         out dx,al                       ;读取的扇区数

                         inc dx                          ;0x1f3
                         mov ax,si
                         out dx,al                       ;LBA地址7~0

                         inc dx                          ;0x1f4
                         mov al,ah
                         out dx,al                       ;LBA地址15~8

                         inc dx                          ;0x1f5
                         mov ax,di
                         out dx,al                       ;LBA地址23~16

                         inc dx                          ;0x1f6
                         mov al,0xe0                     ;LBA28模式,主盘
                         or al,ah                        ;LBA地址27~24
                         out dx,al

                         inc dx                          ;0x1f7
                         mov al,0x20                     ;读命令
                         out dx,al

          .waits:
                         in al,dx
                         and al,0b1000_1000                                ;BSY:1--硬盘忙,DRQ:1--准备好
                         cmp al,0x08
                         jnz .waits                      ;不忙,且硬盘已准备好数据传输
                                                                                        ;BSY:0--不忙,DRQ:1--准备好

                         mov cx,256                      ;总共要读取的字数,一个扇区
                         mov dx,0x1f0
          .readw:
                         in ax,dx
                         mov [bx],ax
                         add bx,2
                         loop .readw

                         pop dx
                         pop cx
                         pop bx
                         pop ax
                  
                         ret                       
                       
;--------------------------------------------------------------------------------
                        times 510-($-$$) db 0
                        db 0x55,0xaa
                       
                       

看不太懂你的,这是我们老师给的示例代码,但是这只读入一个扇区。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-11-24 21:50:11 | 显示全部楼层
15218524174 发表于 2021-11-24 21:34
;文件名:port_hd_hello.asm
                        ;功能:1.读取硬盘逻辑扇区号100处的1个扇区到物理内存0x10000处
                        ; ...

1. 我没有你的这个写代码环境,没办法调试你的程序,就像你没办法使用我写的程序一样
2. 也就是说还差一个写 hello world 到 101 扇区的程序?
硬盘读取命令是 0x20
写入命令是 0x30
其他基本一样
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-11-24 21:50:44 | 显示全部楼层
  1. #void read_sect(uint8_t *buf, size_t start_sect);
  2. read_sect:
  3.     pushl   %ebp
  4.     movl    %esp, %ebp
  5.     pushl   %edi

  6.     # 读取1个扇区
  7.     movb    $1, %al
  8.     movl    $0x1f2, %edx
  9.     outb    %al, %dx

  10.     # 下面发送逻辑扇区号
  11.     # 0~7
  12.     movl    12(%ebp), %ecx
  13.     movl    %ecx, %eax
  14.     movl    $0x1f3, %edx
  15.     outb    %al, %dx

  16.     # 8~15
  17.     movl    %ecx, %eax
  18.     shrl    $8, %eax
  19.     movl    $0x1f4, %edx
  20.     outb    %al, %dx

  21.     # 16~23
  22.     movl    %ecx, %eax
  23.     shrl    $16, %eax
  24.     movl    $0x1f5, %edx
  25.     outb    %al, %dx

  26.     # LBA28模式, 主盘
  27.     # LBA地址24~27
  28.     movl    %ecx, %eax
  29.     shrl    $24, %eax
  30.     andl    $0x0f, %eax
  31.     orl     $0xe0, %eax
  32.     movl    $0x1f6, %edx
  33.     outb    %al, %dx

  34.     # 发送读命令
  35.     movb    $0x20, %al
  36.     movl    $0x1f7, %edx
  37.     outb    %al, %dx

  38.     # 等待硬盘准备好
  39. .L1:
  40.     inb     %dx, %al
  41.     andb    $0x88, %al
  42.     cmpb    $0x08, %al
  43.     jne     .L1

  44.     # 从硬盘读取数据
  45.     movl    8(%ebp), %edi
  46.     movl    $256, %ecx
  47.     movl    $0x1f0, %edx
  48.     cld
  49.     rep     insw

  50.     popl    %edi
  51.     popl    %ebp
  52.     retl
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-11-24 21:51:17 | 显示全部楼层
  1. #void write_sect(const uint8_t *buf, size_t start_sect);
  2. write_sect:
  3.     pushl   %ebp
  4.     movl    %esp, %ebp
  5.     pushl   %esi

  6.     # 写入1个扇区
  7.     movb    $1, %al
  8.     movl    $0x1f2, %edx
  9.     outb    %al, %dx

  10.     # 下面发送逻辑扇区号
  11.     # 0~7
  12.     movl    12(%ebp), %ecx
  13.     movl    %ecx, %eax
  14.     movl    $0x1f3, %edx
  15.     outb    %al, %dx

  16.     # 8~15
  17.     movl    %ecx, %eax
  18.     shrl    $8, %eax
  19.     movl    $0x1f4, %edx
  20.     outb    %al, %dx

  21.     # 16~23
  22.     movl    %ecx, %eax
  23.     shrl    $16, %eax
  24.     movl    $0x1f5, %edx
  25.     outb    %al, %dx

  26.     # LBA28模式, 主盘
  27.     # LBA地址24~27
  28.     movl    %ecx, %eax
  29.     shrl    $24, %eax
  30.     andl    $0x0f, %eax
  31.     orl     $0xe0, %eax
  32.     movl    $0x1f6, %edx
  33.     outb    %al, %dx

  34.     # 发送写命令
  35.     movb    $0x30, %al
  36.     movl    $0x1f7, %edx
  37.     outb    %al, %dx

  38.     # 等待硬盘准备好
  39. .L1:
  40.     inb     %dx, %al
  41.     andb    $0x88, %al
  42.     cmpb    $0x08, %al
  43.     jne     .L1

  44.     # 把数据写入硬盘
  45.     movl    8(%ebp), %esi
  46.     movl    $256, %ecx
  47.     movl    $0x1f0, %edx
  48.     cld
  49.     rep     outsw

  50.     popl    %esi
  51.     popl    %ebp
  52.     retl
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-24 02:49

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表