跳转
短距离跳转
近距离跳转
远距离跳转
远距离绝对地址跳转
jmp3000h:0h
远距离绝对间接地址跳转
函数
函数调用
调用指令
call
返回指令
ret
retf
Near Call
段内调用
[section data] m_real_mode db '[real address mode]', 0dh, 0ah, '$' m_pro_mode db '[protected mode]', 0dh, 0ah, '$' [section .text] proc_real_mode: mov dx, m_real_mode mov ah, 09h int 21h ret proc_protected_mode: mov dx, m_pro_mode mov ah, 09h int 21h ret ..start: mov ax,data mov ds,ax call proc_real_mode ; call <label> call proc_protected_mode ; call <label> mov ah, 4ch int 21h
段内调用也可以通过call seg:offset方式进行调用:
[section data] m_real_mode db '[real address mode]', 0dh, 0ah, '$' m_pro_mode db '[protected mode]', 0dh, 0ah, '$' [section .text] proc_real_mode: mov dx, m_real_mode mov ah, 09h int 21h ret proc_protected_mode: mov dx, m_pro_mode mov ah, 09h int 21h ret ..start: mov ax,data mov ds,ax call seg proc_real_mode:proc_real_mode ; call seg:offset call seg proc_protected_mode:proc_protected_mode ; call seg:offset mov ah, 4ch int 21h
段内调用也可以通过Far Call方式进行调用:
[section data] m_real_mode db '[real address mode]', 0dh, 0ah, '$' m_pro_mode db '[protected mode]', 0dh, 0ah, '$' [section .text] proc_real_mode: mov dx, m_real_mode mov ah, 09h int 21h ret proc_protected_mode: mov dx, m_pro_mode mov ah, 09h int 21h ret ..start: mov ax,data mov ds,ax call far proc_real_mode ; call far <label> call far proc_protected_mode ; call far <label> mov ah, 4ch int 21h
Far Call
段间调用
[section data] m_real_mode db '[real address mode]', 0dh, 0ah, '$' m_pro_mode db '[protected mode]', 0dh, 0ah, '$' [section .proc] proc_real_mode: mov dx, m_real_mode mov ah, 09h int 21h retf proc_protected_mode: mov dx, m_pro_mode mov ah, 09h int 21h retf [section .text] ..start: mov ax,data mov ds,ax call far proc_real_mode ; call far <label> call seg proc_real_mode:proc_real_mode ; call seg:offset call far proc_protected_mode ; call far <label> call seg proc_protected_mode:proc_protected_mode ; call seg:offset mov ah, 4ch int 21h
Inter-privilege-level far call
这是一种Far Call调用另一个段中且在不同特权级别的函数
Task switch
call seg:offset方式
call seg:offset方式既可以用于Near Call,也可以用于Far Call的函数调用。
输出格式
输出格式通过-f参数选项指定。如果没有指定,默认为bin格式。
>nasm a.asm -fbin -o a.bin
>nasm a.asm -f bin -o a.bin
可以通过nasm -hf查看nasm支持的输出格式。
输出格式支持:
* bin flat-form binary files (e.g. DOS .COM, .SYS)
ith Intel hex
srec Motorola S-records
aout Linux a.out object files
aoutb NetBSD/FreeBSD a.out object files
coff COFF (i386) object files (e.g. DJGPP for DOS)
elf32 ELF32 (i386) object files (e.g. Linux)
elf64 ELF64 (x86_64) object files (e.g. Linux)
elfx32 ELFX32 (x86_64) object files (e.g. Linux)
as86 Linux as86 (bin86 version 0.3) object files
obj MS-DOS 16-bit/32-bit OMF object files
win32 Microsoft Win32 (i386) object files
win64 Microsoft Win64 (x86-64) object files
rdf Relocatable Dynamic Object File Format v2.0
ieee IEEE-695 (LADsoft variant) object file format
macho32 NeXTstep/OpenStep/Rhapsody/Darwin/MacOS X (i386) object files
macho64 NeXTstep/OpenStep/Rhapsody/Darwin/MacOS X (x86_64) object files
dbg Trace of all info passed to output stage
elf ELF (short name for ELF32)
macho MACHO (short name for MACHO32)
win WIN (short name for WIN32)
bin
Using the bin Format To Generate .COM Files
section .data message: db 'Welcome!' , 0dh, 0ah db 'X2', 0dh, 0ah db 'version: 1.0.0 2010-02-14 Express Edition', 0dh, 0ah db '(c) Next G', 0dh, 0ah end1: db '$' section .text org 0x100 mov dx, message mov ah, 09h int 21h mov ah, 4ch int 21h
>nasm int21_09_test6.asm -fbin -o int21_09_test6.com
Using the bin Format To Generate .EXE Files
%include "exebin.mac" ; call EXE_begin. this is a macro, with no arguments. EXE_begin [section data] message db 'Welcome!' , 0dh, 0ah db 'X2', 0dh, 0ah db 'version: 1.0.0 2010-02-14 Express Edition', 0dh, 0ah db '(c) Next G', 0dh, 0ah end1 db '$' [section .text] _start: mov dx, message mov ah, 09h int 21h mov ah, 4ch int 21h ; call EXE_end. this is a macro, with no arguments. EXE_end
>nasm -IE:\software\os\nasm-2.14.02\misc int21_09_test3.asm -fbin -o int21_09_test3.exe
coff
global start section .data message: db 'Welcome!' , 0dh, 0ah db 'X2', 0dh, 0ah db 'version: 1.0.0 2010-02-14 Express Edition', 0dh, 0ah db '(c) Next G', 0dh, 0ah end1: db '$' section .text start: ;mov ax, .data mov edx, message mov ah, 09h int 21h mov ah, 4ch int 21h
>nasm int21_09_test6_1.asm -fcoff -o int21_09_test6_1.o
>ld -s int21_09_test6_1.o -o int21_09_test6_1.exe
obj
Using the obj Format To Generate .EXE Files
global _start segment data message db 'Welcome!' , 0dh, 0ah db 'X2', 0dh, 0ah db 'version: 1.0.0 2010-02-14 Express Edition', 0dh, 0ah db '(c) Next G', 0dh, 0ah end1 db '$' segment code ; ..start: _start: mov ax,data mov ds,ax mov dx, message mov ah, 09h int 21h mov ah, 4ch int 21h
>nasm -f obj int21_09_test4.asm -o int21_09_test4.obj
>alink int21_09_test4.obj -entry _start -oEXE -o int21_09_test4.exe
win32
global _start section .data message: db 'Welcome!' , 0dh, 0ah db 'X2', 0dh, 0ah db 'version: 1.0.0 2010-02-14 Express Edition', 0dh, 0ah db '(c) Next G', 0dh, 0ah end1: db '$' section .text _start: ;mov ax, .data mov edx, message mov ah, 09h int 21h mov ah, 4ch int 21h
>nasm int21_09_test6_3.asm -f win32 -o int21_09_test6_3.obj
>ld -s int21_09_test6_3.obj -o int21_09_test6_3.exe
win
global _start section .data message: db 'Welcome!' , 0dh, 0ah db 'X2', 0dh, 0ah db 'version: 1.0.0 2010-02-14 Express Edition', 0dh, 0ah db '(c) Next G', 0dh, 0ah end1: db '$' section .text _start: ;mov ax, .data mov edx, message mov ah, 09h int 21h mov ah, 4ch int 21h
>nasm int21_09_test6_2.asm -f win -o int21_09_test6_2.obj
>ld -s int21_09_test6_2.obj -o int21_09_test6_2.exe
NASM汇编源代码
一个简单的例子,在这个例子中,在汇编代码前后调用了EXE_begin和EXE_end宏。以生成可执行文件(.EXE)头部数据,以及定义一些符号以记录段大小,这些符号在EXE_end生成的头部数据中引用。
%include "exebin.mac" ; call EXE_begin. this is a macro, with no arguments. EXE_begin ;global _start ;section .bss ;section .data ;section .text _start: ; non-local label mov eax,4 mov ebx,1 ; call EXE_end. this is a macro, with no arguments. EXE_end
编译时指定include路径,-f指定为bin格式。编译器将根据bin文件生成可执行文件(.EXE),主要就是生成可执行文件(.EXE)头部数据,以及定义一些符号以记录段大小,这些符号在EXE_end生成的头部数据中引用。
>nasm -IE:\software\os\nasm-2.14.02\misc nasm_test4.asm -fbin -o nasm_test4.exe
中断
BIOS中断
13H中断:磁盘中断。直接磁盘服务(Direct Disk Service)
02H功能号:读扇区
U_DATA_SEG equ 0x3000 org 0x7c00 segment .text ; es, user data segment mov dx, U_DATA_SEG mov es, dx mov ah, 02h ;mov dl, 81h ; drive 0 驱动器 00H~7FH:软盘;80H~0FFH:硬盘 mov dl, 80h ;mov dl, 0 mov dh, 0 ; head 0 磁头 mov ch, 0 ; track 柱面 mov cl, 1 ; sector 扇区 mov al, 1 mov bx, 0 ; 将指定扇区读到es:bs位置 int 13h jnc read_sector_ok read_sector_error: mov si, m_read_sector_error p1: mov al, [si] add si, 1 cmp al, 0x00 je endl mov ah, 0x0e mov bx, 0x0f int 0x10 jmp p1 read_sector_ok: mov si, m_read_sector_ok p0: mov al, [si] add si, 1 cmp al, 0x00 je jmp_to mov ah, 0x0e mov bx, 0x0f int 0x10 jmp p0 jmp_to: mov bx, 0 jmp 3000h:0h endl: hlt jmp endl m_read_sector_ok: db 0x0a, 0x0a db "[ook] read sector", 0dh, 0ah db 0x0a, 0x0a db 0x00 m_read_sector_error: db 0x0a, 0x0a db "[err] read sector", 0dh, 0ah db 0x0a, 0x0a db 0x00 ; MBR扇区位于整个硬盘的第一个扇区. ; 硬盘扇区为512字节,所以主引导程序大小仅能也只能512字节。 times 510-($-$$) db 0x00 ; MBR结束标志 db 0x55, 0xaa
21H中断
9H功能号输出字符串
%include "exebin.mac" ; call EXE_begin. this is a macro, with no arguments. EXE_begin section .data message db 'Welcome!' , 0dh, 0ah db 'X2', 0dh, 0ah db 'version: 1.0.0 2010-02-14 Express Edition', 0dh, 0ah db '(c) Next G', 0dh, 0ah end1 db '$' section .text _start: mov dx, message mov ah, 09h int 21h mov ah, 4ch int 21h ; call EXE_end. this is a macro, with no arguments. EXE_end
显卡
文本模式
居中显示字符串
org 0x100 [section .text] mov bx, 0b800h mov es, bx mov di, 78 mov al, 'A' mov ah, 00000010B ; mov [es:di], ax add di, 2 mov al, 'A' mov ah, 00000010B ; mov [es:di], ax mov di, 160 + 78 mov al, 'B' mov ah, 00000010B ; mov [es:di], ax add di, 2 mov al, 'B' mov ah, 00000010B ; mov [es:di], ax mov di, 160 * 2 + 78 mov al, 'C' mov ah, 00000010B ; mov [es:di], ax add di, 2 mov al, 'C' mov ah, 00000010B ; mov [es:di], ax mov ah, 4ch int 21h
显示模式(00H 40×25 16色 文本; 01H 40×25 16色 文本)下居中显示字符串的问题
在设置显示模式后,显存中通过80个字节(40个字节的字符,40个字节的颜色属性,反映到显示器屏幕上就是一行40个字符),但读取显示模式,显示器屏幕字符列数还是80,不是40。
org 0x100 [section .text] mov ah, 00h ; 设置显示模式 mov al, 01h ; 显示模式: 00H 40×25 16色 文本; 01H 40×25 16色 文本 int 10h mov bx, 0b800h mov es, bx mov di, 78 mov al, 'A' mov ah, 11010010B ; mov [es:di], ax add di, 2 mov al, 'A' mov ah, 11010010B ; mov [es:di], ax mov di, 80 + 78 mov al, 'B' mov ah, 11010010B ; mov [es:di], ax add di, 2 mov al, 'B' mov ah, 11010010B ; mov [es:di], ax mov di, 80 * 2 + 78 mov al, 'C' mov ah, 00000010B ; mov [es:di], ax add di, 2 mov al, 'C' mov ah, 00000010B ; mov [es:di], ax mov ah, 4ch int 21h
图形模式
画图
画点:图形模式下,在屏幕左上角画一个点
org 0x100 [section .text] ; 通过BIOS设置VGA模式 mov ah, 00h mov al, 12h int 10h ;以下对VGA控制器设置 ;将VGA控制器,设置为写模式2 mov dx,3ceh mov al,5 out dx,al ;选择 模式选择寄存器 为当前可用寄存器 mov dx,3cfh mov al,2 out dx,al ;将模式2设为当前写模式 ;对位屏蔽寄存器设置,使传送给0a000h的八个象素中设位1的象素为有效。 mov dx,3ceh mov al,8 out dx,al ;选择 位屏蔽寄存器 为当前可用寄存器 mov dx,3cfh mov al,10000000b ;让八个象素前1个有效,后7个无效 out dx,al ;对0a000h地址进行操作 ;设置初始参数 mov ax,0a000h ;段地址 mov es,ax mov bx,00000h ;起始偏移 mov al,0ah ;绿色 mov [es:bx],al ;mov ah, 4ch ;int 21h last: hlt jmp last
画线:图形模式下,在屏幕顶部画一条线
org 0x100 [section .text] ; 通过BIOS设置VGA模式 mov ah, 00h mov al, 12h int 10h ;以下对VGA控制器设置 ;将VGA控制器,设置为写模式2 mov dx,3ceh mov al,5 out dx,al ;选择 模式选择寄存器 为当前可用寄存器 mov dx,3cfh mov al,2 out dx,al ;将模式2设为当前写模式 ;对位屏蔽寄存器设置,使传送给0a000h的八个象素中设位1的象素为有效。 mov dx,3ceh mov al,8 out dx,al ;选择 位屏蔽寄存器 为当前可用寄存器 mov dx,3cfh ;mov al,11110000b ;让八个象素前四个有效,后四个无效 mov al,11111111b out dx,al ;对0a000h地址进行操作 ;设置初始参数 mov ax,0a000h ;段地址 mov es,ax mov bx,00000h ;起始偏移 mov al,0ah ;绿色 mov cx, 80; 0ffffh ;循环次数 ;对内存循环操作写入 jmp _rep _rep: mov [es:bx],al inc bx loop _rep ;mov ah, 4ch ;int 21h last: hlt jmp last
画线:图形模式下,在屏幕顶部画一条点线
org 0x100 [section .text] ; 通过BIOS设置VGA模式 mov ah, 00h mov al, 12h int 10h ;以下对VGA控制器设置 ;将VGA控制器,设置为写模式2 mov dx,3ceh mov al,5 out dx,al ;选择 模式选择寄存器 为当前可用寄存器 mov dx,3cfh mov al,2 out dx,al ;将模式2设为当前写模式 ;对位屏蔽寄存器设置,使传送给0a000h的八个象素中设位1的象素为有效。 mov dx,3ceh mov al,8 out dx,al ;选择 位屏蔽寄存器 为当前可用寄存器 mov dx,3cfh ;mov al,11110000b ;让八个象素前四个有效,后四个无效 mov al,10101010b out dx,al ;对0a000h地址进行操作 ;设置初始参数 mov ax,0a000h ;段地址 mov es,ax mov bx,00000h ;起始偏移 mov al,0ah ;绿色 mov cx, 80; 0ffffh ;循环次数 ;对内存循环操作写入 jmp _rep _rep: mov [es:bx],al inc bx loop _rep ;mov ah, 4ch ;int 21h last: hlt jmp last
画线:图形模式下,在屏幕顶部画一条点线(和上面的效果不一样)
[section .text] ; 通过BIOS设置VGA模式 mov ah, 00h mov al, 12h int 10h ;以下对VGA控制器设置 ;将VGA控制器,设置为写模式2 mov dx,3ceh mov al,5 out dx,al ;选择 模式选择寄存器 为当前可用寄存器 mov dx,3cfh mov al,2 out dx,al ;将模式2设为当前写模式 ;对位屏蔽寄存器设置,使传送给0a000h的八个象素中设位1的象素为有效。 mov dx,3ceh mov al,8 out dx,al ;选择 位屏蔽寄存器 为当前可用寄存器 mov dx,3cfh ;mov al,11110000b ;让八个象素前四个有效,后四个无效 mov al,10110101b out dx,al ;对0a000h地址进行操作 ;设置初始参数 mov ax,0a000h ;段地址 mov es,ax mov bx,00000h ;起始偏移 mov al,0ah ;绿色 mov cx, 80; 0ffffh ;循环次数 ;对内存循环操作写入 jmp _rep _rep: mov [es:bx],al inc bx loop _rep ;mov ah, 4ch ;int 21h last: hlt jmp last
键盘
我们在使用键盘进行输入的时候,键盘上面的键在按下和松开都会产生对应的扫描码,按下时产生的扫描码称为通码,松开时产生的称为断码。
扫描码长度为一个字节,通码的第7位为0,断码的第7位为1,即:
断码=通码+80h
键盘输入产生的扫描码送入到输入缓冲区。输入缓冲区是键盘内部的输入缓冲寄存器,对应60h端口,可以通过in端口指令从该端口将送入到输入缓冲区中的扫描码读取出来,输入缓冲区中的扫描码读取出来后会被移出,而不会保留在输入缓冲区中。这样才能继续接收键盘输入送入的扫描码。
主引导程序
NASM编写主引导程序的例子,该例子检查当前的运行模式,检查当前是运行在实模式还是保护模式:通过检查CR0控制寄存器的第0位(PE位)来判断当前运行的模式。
org 0x7c00 start: mov ax, cs mov ss, ax mov ds, ax mov es, ax mov eax, cr0 bt eax, 0 jc protected_mode real_mode: mov si, m_real_mode r: mov al, [si] add si, 1 cmp al, 0x00 je endl mov ah, 0x0e mov bx, 0x0f int 0x10 jmp r protected_mode: mov si, m_real_mode p: mov al, [si] add si, 1 cmp al, 0x00 je endl mov ah, 0x0e mov bx, 0x0f int 0x10 jmp p endl: hlt jmp endl m_real_mode: db 0x0a, 0x0a db "[real address mode]", 0dh, 0ah db 0x0a, 0x0a db 0x00 m_pro_mode: db 0x0a, 0x0a db "[protected mode]", 0dh, 0ah db 0x0a, 0x0a times 510-($-$$) db 0x00 db 0x55, 0xaa
Bochs
这部分参考另一篇文章:https://www.iteye.com/blog/lobin-2375299
QEMU
这部分参考另一篇文章:https://www.iteye.com/blog/lobin-673570
有关汇编以及8086可参考另一篇文章:https://www.iteye.com/blog/lobin-1549433
有关386可参考另一篇文章:https://lobin.iteye.com/blog/2026860
有关686可参考另一篇文章:https://lobin.iteye.com/blog/2041898
有关汇编以及arm可参考另一篇文章:https://lobin.iteye.com/blog/2046869
相关推荐
NASM开发了IDE,听起来很复杂,但并不像看上去那么复杂。虽然汇编编程不是那么容易的微分方程(可能是一个坏例子)。该IDE设计重量轻,但同时使用方便。因为汇编编程对于所有的命令行来说都是一件痛苦的事情。现在有...
Nasm中文手册nasm第一章: 简介1.1 什么是NASM NASM是一个为可移植性与模块化而设计的一个80x86的汇编器。它支持相当多 的目标文件格式,包括Linux和'NetBSD/FreeBSD','a.out','ELF','COFF',微软16 位的'OBJ'...
NASM 源码文件名 -o 输出文件名 NASM是编译器名,-O是输出命令 如编译附带的操作系统(这个文件有两种模式,1完全脱离系统,2运行于WINDOW虚拟机,这里我就不多说了)的方法是: NASM boot.asm -o boot.com 3....
NASM是一个为可移植性与模块化而设计的一个80x86的汇编器。它支持相当多 的目标文件格式,包括Linux和'NetBSD/FreeBSD','a.out','ELF','COFF',微软16位的'OBJ'和'Win32'。它还可以输出纯二进制文件。它的语法设计得...
汇编编译器 win32nasm编译器nasm编译器nasm编译器
NASM 编译器NASM 编译器NASM 编译器NASM 编译器NASM 编译器NASM 编译器NASM 编译器NASM 编译器NASM 编译器
nasm手册nasm手册nasm手册nasm手册
nasm_v2.14RC14官网源版资源(日期戳记为2018-06-28 02:46),搜集整理的汇编语言学习和开发环境。 下载解压缩包后可阅读说明和中文版手册。 本压缩包内容可以在WINDOWS 10环境下搭建完整的汇编语言学习、开发环境。...
NASM汇编语言手册,NASM全称The Netwide Assembler,是一款基于80x86和x86-64平台的汇编语言编译程序,其设计初衷是为了实现编译器程序跨平台和模块化的特性。NASM支持大量的文件格式,包括Linux,*BSD,a.out,ELF...
NASM汇编文档 NASM语法 NASM语法
nasm教程和源码和Nasm使用手册,nasm编译器,nasm与gas的对比
NASM中文手册.pdf 学nasm必备哈 1.1 什么是NASM [1]NASM是一个为可移植性与模块化而设计的一个80x86的汇编器。它支持相当多 的目标文件格式,包括Linux和'NetBSD/FreeBSD','a.out','ELF','COFF',微软16 位的'OBJ'...
NASM中文手册 NASM中文手册 NASM中文手册
1.1 什么是NASM NASM是一个为可移植性与模块化而设计的一个80x86的汇编器。 它支持相当多 的目标文件格式,包括Linux和'NetBSD/FreeBSD','a.out','ELF','COFF',微软16 位的'OBJ'和'Win32'。它还可以输出纯二...
VS2015-2017使用NASM编译汇编文件所需的nasm v2.15最新版 内有自动安装的批处理,也有可以自动下载并安装2.13版的批处理
nasm汇编编译工具
1.Nasm中文教程(共10章)pdf文件 2.nasm-2.15.05-installer 3.nasm-2.15.05-win64 4.nasmx-1.4
nasm是当前可以找到的最佳汇编语言编译器,首先比masm,tasm更新,支持的处理器指令集更全面,masm太古老了,如同活化石。yasm的语法太古怪,不适合学习者。如果哪位同学想学习汇编,我认为nasm是最佳工具。但是国内...
这是一本介绍如何使用nasm的书。 NASM是一个为可移植性与模块化而设计的一个80x86的汇编器。它支持相当多 的目标文件格式,包括Linux和'NetBSD/FreeBSD','a.out','ELF','COFF',微软16 位的'OBJ'和'Win32'。它还...
Nasm 汇编语言教程 中英双语及源代码。中英对照看,更清晰。