用x86汇编写hello world(一)

系统环境:基于Intel CPU的mac电脑,装有vim(自带),nasm(通过brew安装)和virtualbox(从官网下载dmg安装)。 

创建虚拟机:在virtualbox中创建一个名为“learn”的虚拟机,虚拟磁盘选择vhd格式,大小2GB,固定大小,命名为learn.vhd,放在/Users/<当前用户>/programs/asm目录下(因为固定大小的vhd最简单,方便后面的写入操作)。

编写代码:打开终端,在vim中输入以下代码,保存为printstr.asm

[bits 16]
mov ax, 0x07c0
mov ds, ax	;ds==0x07c0, boot sector
mov ax, 0xb800
mov es, ax
mov si, 0	;si is the index of the array 
mov di, 0	;di is the offset of video memory
jmp near print

message db "Hello world!", 0

print:
	mov bl, message[si]
	inc si
	mov [es:di], bl
	inc di
	mov byte [es:di], 0x07
	inc di
	cmp byte message[si], 0x00
	jne print

halt:
	jmp halt

times 510-($-$$) db 0
db 0x55
db 0xaa

在汇编、运行之前,先分析一下代码。

Intel x86 CPU在开机后,会进入16位实模式,[bits 16]告诉汇编器,以16位方式汇编。

在实模式下,CPU用“段地址+偏移地址”方式寻址,默认段寄存器为ds,另外es也可用作段寄存器。0x07c00为硬盘主引导扇区加载到内存后的起始地址,0xb8000为显存起始地址。

程序首先初始化段寄存器ds为0x07c0,以保证后面对message,print和halt标号的寻址正常工作,然后初始化es为0xb800。注意,初始化ds时,不能直接使用“mov ds, 0x07c0”,es同理,因为CPU不允许直接把立即数赋值给段寄存器。本程序用数组形式表示字符串“Hello world!”,si表示message数组的当前索引,di表示相对于显存起始地址的偏移量。jmp near print表示无条件跳转到print。在内存中,指令和数据的形式没有区别,都是二进制数。为了避免把hello world字符串当成指令执行而导致错误,必须跳过这个字符串。

到了print,程序正式开始工作。si的初始值为0,此时,“mov bl, message[si]”把message[0],即字符‘H’加载到寄存器bl。然后,si值加1,指向下一个字符‘e’。di的初始值为0,此时“mov [es:di], bl”将bl中的内容存储到es与di合成的内存地址,即0xb8000。然后,di的值加1,es:di合成的地址变为0xb8001。接着,程序将字体格式数据0x07(黑底,白字,不闪烁)写入0xb8001,di再加1,[es:di]变为0xb8002。然后比较此时si指向的字符ASCII码是否为0,如果不为0,说明字符串没有结束,跳转到print,继续循环;如果为0,说明字符串已结束,退出循环。此时,si指向的字符为‘e’,ASCII码不为0,跳转到print,继续循环。程序再把字符‘e’写到0xb8002,把0x07写到0xb8003......如此循环往复,直到碰到字符串后面的0,退出此循环,来到halt。

halt下的指令为“jmp halt”,是一个死循环,计算机会一直执行“jmp halt”。这个死循环是必要的,因为如果没有这个死循环,计算机会把后面的内存空间的内容当成指令来执行,导致错误。

“times 510-($-$$) db 0”是一条nasm伪指令,表示从当前位置开始填充0,直到第510个字节,db 0x55和db 0xaa表示填充0x55和0xaa。编写上述伪指令也是必要的,因为主引导扇区的相关规范规定主引导扇区为512字节,且以55aa结尾。

汇编:进入printstr.asm所在目录,在终端输入以下命令

nasm printstr.asm -o printstr.bin -f bin

写入vhd虚拟磁盘:在终端输入

dd if=printstr.bin of=../learn.vhd bs=512 count=1 conv=notrunc

此处一定要加上“conv=notrunc”选项。如果不加,learn.vhd会变成512字节。加上后,表示把printstr.bin写入到learn.vhd的前512字节,并保留learn.vhd后面原有的内容。只有加上这个选项,程序才能正常工作。

运行:打开virtualbox,运行learn虚拟机,即可看到在虚拟机开机后,屏幕上显示“Hello world!”

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qifeng_xiaozi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值