汇编上机2

继续从作业代码出发来学习知识点

任务一

题目:

代码

.model small

.stack 100h

.data

    scores db 46, 68, 88, 87, 76, 89, 99, 65, 100, 80 ; 学生成绩

    S5 db 0 ; 低于60分人数

    S6 db 0 ; 60-69分人数

    S7 db 0 ; 70-79分人数

    S8 db 0 ; 80-89分人数

    S9 db 0 ; 90-99分人数

    S10 db 0 ; 100分人数

.code

main proc

    mov cx, 10              ; 循环次数

    lea si, scores          ; 成绩数组指针

check_score:

    lodsb                   ; 读取一个成绩到 AL

    cmp al, 60

    jl below_60

    cmp al, 70

    jl between_60_69

    cmp al, 80

    jl between_70_79

    cmp al, 90

    jl between_80_89

    cmp al, 100

    jl between_90_99

    jmp exactly_100

below_60:

    inc S5                  ; 低于60分人数加1

    jmp next_score

between_60_69:

    inc S6                  ; 60-69分人数加1

    jmp next_score

between_70_79:

    inc S7                  ; 70-79分人数加1

    jmp next_score

between_80_89:

    inc S8                  ; 80-89分人数加1

    jmp next_score

between_90_99:

    inc S9                  ; 90-99分人数加1

    jmp next_score

exactly_100:

    inc S10                 ; 100分人数加1

next_score:

    loop check_score        ; 循环直到所有成绩处理完毕

    ; 程序结束

    mov ax, 4C00h

    int 21h

main endp

end main

  • 段定义和数据初始化

.model small

.stack 100h

.data

    scores db 46, 68, 88, 87, 76, 89, 99, 65, 100, 80 ; 学生成绩

    S5 db 0 ; 低于60分人数

    S6 db 0 ; 60-69分人数

    S7 db 0 ; 70-79分人数

    S8 db 0 ; 80-89分人数

    S9 db 0 ; 90-99分人数

    S10 db 0 ; 100分人数

.data:定义数据段。

scores:定义一个包含10个成绩的字节数组。

S5 到 S10:定义用于存储各分数段人数的字节变量,并初始化为 0。

Db:是define byte的缩写,用于在数据中定义一个或多个字节数据,允许程序员在内存中分配和初始化一个或多个字节的存储空间。

  • 代码段和主程序

.code

main proc

    mov cx, 10              ; 循环次数

    lea si, scores          ; 成绩数组指针

  1. main proc:定义主过程

1.CX寄存器,(1)作为循环计数器

CX 常用于循环操作中,用来保存循环的次数。

在使用 LOOP 指令时,CX 会自动减少,并在其值为零时结束循环。

2在字符串操作中的用途:

·CX 常用于字符串指令(如 REP MOVSBREP STOSB 等)中,指定要操作的字节数或字数。

  1. Si寄存器是源索引寄存器
  • SI 寄存器通常用作源指针,用于字符串操作和数组处理。
  • 在字符串操作指令(如 LODSB, LODSW)中,SI 指向源数据的起始地址,并在操作完成后自动更新。

LEA 指令

  • LEA 指令用于加载内存地址到寄存器中,而不是加载内存地址所指向的数据。
  • 语法:LEA dest, source
    • dest 是目标寄存器。
    • source 是内存地址表达式。

LEA 指令的主要作用是计算复杂的地址表达式,而不会实际访问内存。

  1. 分数段判断和统计

check_score:

    lodsb                   ; 读取一个成绩到 AL

    cmp al, 60

    jl below_60

    cmp al, 70

    jl between_60_69

    cmp al, 80

    jl between_70_79

    cmp al, 90

    jl between_80_89

    cmp al, 100

    jl between_90_99

    jmp exactly_100

  • lodsb:从 si 指针指向的内存地址加载一个字节到 al,并自动增加 si
  • cmp al, 60:比较 al 和 60。
  • jl below_60:如果 al 小于 60,跳转到 below_60 标签。
  • 依此类推,继续比较 al 和其他分数段的上限值,并跳转到相应的处理标签。

jl是一个跳转指令,表示“如果小于则跳转(jump if less)”

  1. 统计各分数段人数

below_60:

    inc S5                  ; 低于60分人数加1

    jmp next_score

between_60_69:

    inc S6                  ; 60-69分人数加1

    jmp next_score

between_70_79:

    inc S7                  ; 70-79分人数加1

    jmp next_score

between_80_89:

    inc S8                  ; 80-89分人数加1

    jmp next_score

between_90_99:

    inc S9                  ; 90-99分人数加1

    jmp next_score

exactly_100:

    inc S10                 ; 100分人数加1

next_score:

loop check_score        ; 循环直到所有成绩处理完毕

  1.    

; 程序结束

    mov ax, 4C00h

    int 21h

main endp

end main

任务二:(2)

.model small

.stack 100h

.data

#$是一个字符串结束的标志

prompt db 'Enter a lowercase letter: $'

#newline表示可以将光标移动到下一行的开头

#‘0Dh’是回车字符,将光标移动到当前行的开头

#‘0Ah’是换行字符 ,将光标移动下一行

    newline db 0Dh, 0Ah, '$'

    output db '$'

.code

main proc

#将@data的段地址 加载到ax寄存器中

#复习逻辑地址:由段地址和偏移地址构成

mov ax, @data

#ds数据段寄存器

mov ds, ax

#es附加段寄存器

    mov es, ax

#这是一个标签label,表示程序或循环的开始位置。以便可以使用跳转指令(如jmp)跳转到该位置

start:

# lea指令:是“加载有效地址(load effective address)的缩写”

#dx是目标寄存器,用于存放有效地址

#这段代码将prompt字符串的地址加载到dx寄存器中,而不是加载字符串的内容

lea dx, prompt

#ah是ax寄存器的高字节。09h是dos的一个中断服务号,用于显示字符串

#这里将‘09h’移动到‘ah’寄存器中,告诉DOS要调用的是显示字符串服务

mov ah, 09h

#int指令用于触发终端

#‘21h’是DOS的中断号,负责各种服务系统。

#当‘ah’寄存器中包含‘09h’时,调用‘21h会除法显示字符串操作’

#dx寄存器应包含要显示的字符串地址,该字符串必须以$’结尾。

    int 21h

; 读取键盘输入

#将01h移动到ah寄存器中

mov ah, 01h

#dos中断21h的上下文,‘ah’寄存器的值决定了要执行的具体功能,‘01h’的功能号表示读取键盘输入的一个字符,但字符不会显示在屏幕上

int 21h

#al寄存器包含刚刚输入的值

    mov bl, al           ; 保存输入字符

    ; 检查是否是小写字母

    cmp al, 'a'

    jb end_program       ; 如果小于 'a',结束程序

    cmp al, 'z'

    ja end_program       ; 如果大于 'z',结束程序

; 转换为大写字母

#小写字母‘a’到‘z’的asc码是97到122(16进制为61h到7Ah)

#大写字母‘A’到‘Z’的asc码是65到90(16进制为41h到5Ah)

#小写字母和对应大写字母 之间的差值是32(十六进制为20h)

    sub al, 20h

    ; 显示大写字母

    mov output, al

    lea dx, output

    mov ah, 09h

    int 21h

    ; 显示新行

    lea dx, newline

    mov ah, 09h

    int 21h

    jmp start            ; 返回开始,继续读取输入

end_program:

    ; 程序结束

    mov ax, 4C00h

    int 21h

main endp

end main

  • 数据段

解析

.data

    prompt db 'Enter a lowercase letter: $'

    newline db 0Dh, 0Ah, '$'

    output db '$'

  • prompt:提示用户输入字符的字符串。
  • newline:新行字符,用于在输出后换行。
  • output:用于存储并显示转换后的大写字母。

  • 代码段

.code

main proc

    mov ax, @data

    mov ds, ax

    mov es, ax

  1. ds:数据段寄存器
  2. Es:附加段寄存器es,用于显示字符串
  • 条件跳转指令
  1. jb(jump if below):如果无符号比较结果是小于,则跳转到指定的标签
  2. ja(jump if above):如果无符号比较结果是大于,则跳转到指定的标签

上面的jl是有符号比较

五.DOS编程:面向磁盘操作系统编程

  • 6
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值