Skip to content

什么是汇编语言

约 543 个字 72 行代码 预计阅读时间 4 分钟

汇编语言总括

机器语言由 01 串组成,我们不可能直接通过输入 01 串来进行计算机操作,但是计算机也无法理解人类语言,因此才需要介于人类语言和机器语言之间的计算机语言。

称越接近人类语言的计算机语言越高级,那么计算机语言可分为高级语言、中级语言和低级语言三类。比如 BASIC,Pascal,Fortran 等都属于高级语言,C语言属于中级语言,而汇编语言则属于低级语言。

汇编语言的英文名称是 assembly language ,简称 ASM

不同类型的 CPU 的机器语言各不相同,故不同类型的 CPU 对应的汇编语言也各不相同,比如内置 M1 芯片的苹果电脑和内置 Intel 芯片的PC机,它们的汇编语言是不一样的。

另外,汇编语言还和操作系统有关系,因为汇编语言不像C语言一样具有标准库函数,程序要做到输入输出必然要调用操作系统的资源,而不同操作系统提供给用户的接口是不一样的。

  • DOS 下的汇编语言要进行输入输出时需要调用 int 21h 进行中断
  • Windows 下的汇编语言要进行输入输出时需要调用系统函数的 API
  • Linux 系统下的汇编语言要进行输入输出则需要调用 int 80h 进行中断

由于DOS和Windows都是基于Intel CPU的,二者汇编语言有很多相似之处

现代操作系统对用户程序权限进行了限制,导致无法执行 cli,sti,int 等特权指令,因此本课程选用DOS操作系统下的 8086 汇编语言进行讲解。

第一个汇编语言程序

data segment
s db "Hello,world!", 0Dh, 0Ah,'$' ; db: define bytes
data ends

code segment
assume cs:code, ds:data
main:
    mov ax, seg s ; 等效于 mov ax, data
    mov ds, ax
    mov ah, 9
    mov dx, offset s
    int 21h ; 输出字符串 DS:DX -> '$'-terminated string
    mov ah, 4Ch
    int 21h
code ends
end main

程序输出看不到的话就使用管道 ./hello.exe > output.txt 。不过更推荐使用如下中断查看:

    mov ah, 1
    int 21h ; 敲任意键继续

只使用代码段在屏幕上输出 Hello, world! :

code segment
assume cs:code, ds:code
main:
    push cs
    pop  ds  ; DS=CS
    mov ah, 9
    mov dx, offset hi
    int 21h
    mov ah, 4Ch
    int 21h
hi db 'Hello,world!', 0Dh, 0Ah, '$'
code ends
end main

一个 Windows 下的汇编语言程序,作用为计算 1 到 100 的和并输出

.386 ;说明要用到32位寄存器 eax 等
.model flat, stdcall
option casemap :none

include include\windows.inc
include include\kernel32.inc
include include\user32.inc

includelib lib\kernel32.lib
includelib lib\user32.lib

.data
result db 100 dup(0); dup:duplicate重复
;char result[100]={0};
format db "%d",0; db:define byte字节类型
; char format[3]="%d";       "%d",0 相当于C语言的 "%d\0"
prompt db "The result",0

.code
main:         ; 标号
    mov eax, 0; eax:extended ax
    mov ebx, 1
again: ; again 是 label,可作为跳转指令或者 call 的目标地址
    add eax, ebx; eax=0+1+2+3
    add ebx, 1  ; ebx=4
    cmp ebx, 100; cmp:compare
    jbe again   ; jbe:jump if below or equal
invoke wsprintf, offset result, offset format, eax
; windows系统内部的函数,对应C语言标准库函数 sprintf
; wsprintf(&result[0], &format[0], eax);
; 例如 char buf[100]; wsprintf(buf, "%d", 5050); 将 5050 以字符串形式保存在数组 buf 中("5050\0")
invoke MessageBox,0,offset result,offset prompt,0
; 也是windows系统内部的函数,
; MessageBox(0, &result[0], &prompt[0], 0);
; 作用为弹框输出,标题为 prompt ,正文为 result ,按钮式样为 0
; 第一个参数用来指定弹框的父窗口的编号,当为 0 时表示没有父窗口
; 为什么不直接弹 5050? 因为 MessageBox 只能弹字符串
    ret
end main; 指定程序的起始执行点
         ; end后面的标号决定了程序刚开始
         ; 运行时的eip的值。
Comments: