跳转
短距离跳转
近距离跳转
远距离跳转
远距离绝对地址跳转
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(Netwide Assembler)是一个流行的开源汇编器,主要用于编写x86架构的汇编语言程序。NASM的设计目标是提供高度的可移植性和模块化功能,支持多种目标文件格式,包括但不限于Linux下的ELF格式、NetBSD/FreeBSD下...
NASM开发了IDE,听起来很复杂,但并不像看上去那么复杂。虽然汇编编程不是那么容易的微分方程(可能是一个坏例子)。该IDE设计重量轻,但同时使用方便。因为汇编编程对于所有的命令行来说都是一件痛苦的事情。现在有...
**NASM 汇编器详解** NASM(Netwide Assembler)是当前广泛使用的x86和x86-64架构的汇编语言编译器,它为程序员提供了编写高效、可移植的底层代码的工具。在“nasm-2.16.01.tar.gz”这个压缩包中,包含的是NASM的...
《NASM汇编编译器详解与应用》 NASM,全称为Netwide Assembler,是一款流行的、开源的、支持Intel x86架构的汇编语言编译器。它的名称来源于其开发者最初的目标——成为一个“网络广泛适用”的汇编器。在本文中,...
**NASM汇编编译器** NASM(Netwide Assembler)是一款强大的、开源的、跨平台的汇编器,支持X86和X64架构。它在Windows、Linux以及其他Unix-like系统上都能正常工作,是编写低级别程序、系统软件以及驱动程序时常用...
**NASM汇编语言教程与源码解析** NASM(Netwide Assembler)是一款流行的、开源的、针对Intel x86架构的汇编语言编译器。它支持多种目标格式,包括Linux的ELF、Windows的COFF以及FreeBSD和其他系统的格式。在汇编...
**NASM汇编语言编译器** NASM(Netwide Assembler)是一款流行的开源汇编语言编译器,尤其在x86和x64架构上广泛应用。它支持多种目标格式,包括Intel 8086到现代的x86_64处理器,以及Linux、Windows、FreeBSD等操作...
NASM(Netwide Assembler)是一个开源的汇编语言编译器,专门为80x86架构设计,支持多种目标文件格式,包括Linux下的ELF(Executable and Linkable Format)和NetBSD/FreeBSD下的a.out格式,以及Windows下的OBJ和Win...
**NASM源代码详解** NASM(Netwide Assembler)是一种流行的、开源的、支持Intel x86架构的汇编语言编译器。它被广泛用于编写操作系统、内核、驱动程序以及对性能有极高要求的低级应用程序。在本文中,我们将深入...
### NASM中文手册知识点概述 #### 一、NASM简介 **1.1 什么是NASM** NASM(Network Assembler)是一款专为可移植性和模块化设计的80x86汇编器。它支持多种目标文件格式,如Linux、NetBSD/FreeBSD、a.out、ELF、...
在本文中,我们将深入探讨如何在Visual Studio 2015环境下使用NASM(Netwide Assembler)编译32位汇编语言程序。NASM是一款功能强大的、开源的汇编器,支持X86和X86_64架构,广泛应用于Windows、Linux和Mac OS等操作...
**NASM汇编编译器介绍** NASM(Netwide Assembler)是一款开源、免费的x86架构汇编语言编译器,广泛应用于Linux、Windows以及其他多种操作系统。它支持Intel和AT&T两种语法风格,并且具有高度可移植性和易用性。...
**NASM汇编器详解** NASM(Netwide Assembler)是一个流行的开源X86汇编语言编译器,适用于多种操作系统,包括Windows、Linux、FreeBSD等。标题中的"nasm-0.98.36-win32.zip"指的是NASM的一个特定版本——0.98.36,...
**NASM汇编器介绍** NASM(Netwide Assembler)是一款开源、免费的汇编语言编译器,主要用于x86和x64架构的计算机。标题中的“nasm-2.13.01-win64”指的是该软件的特定版本,即2.13.01,专为Windows 64位操作系统...
NASM 源码文件名 -o 输出文件名 NASM是编译器名,-O是输出命令 如编译附带的操作系统(这个文件有两种模式,1完全脱离系统,2运行于WINDOW虚拟机,这里我就不多说了)的方法是: NASM boot.asm -o boot.com 3....
**NASM开源汇编编译器详解** NASM(Netwide Assembler)是一款高效、开源的x86架构汇编语言编译器,它支持多种操作系统,包括Windows、Linux、FreeBSD、OpenBSD等。 NASM的设计目标是提供一个简单易用、功能强大的...
**NASM汇编语言详解** NASM(Netwide Assembler)是一种流行的、开源的、支持Intel x86架构的汇编语言编译器。它以其简单易读的语法和广泛的平台支持而受到开发者喜爱。在本文中,我们将深入探讨NASM汇编语言的基本...
NASM是一个为可移植性与模块化而设计的一个80x86的汇编器。它支持相当多 的目标文件格式,包括Linux和'NetBSD/FreeBSD','a.out','ELF','COFF',微软16位的'OBJ'和'Win32'。它还可以输出纯二进制文件。它的语法设计得...
NASM(Netwide Assembler)是一款流行的开源汇编语言编译器,专为x86和x64架构设计。标题中的"nasm-2.14.02.tar.gz"表明这是NASM的2.14.02版本,采用的是tar.gz格式的压缩包,这种格式常见于Linux和Unix系统中,用于...