NOS 之 NASM,汇编链接问题

本文详细介绍了NASM汇编器的使用,包括全局和外部函数声明、编译和链接过程、指令语法以及如何创建.EXE文件。讲解了如`GLOBAL`、`EXTERN`、`INCBIN`等关键字的用法,并提到了与C语言的交互以及如何处理二进制文件。同时,还探讨了汇编程序中无限循环、计算符号地址和段定位等概念。
摘要由CSDN通过智能技术生成

在function文件里写这个:

global _func

在main文件里写这个

 

extern _func

然后编译时都先用nasm编译成obj,然后用ld链接到一块。

nasm如果不提供输出文件格式,默认的输出文件格式是 bin

NASM 在缺省状态下是一个两遍的汇编器。

mov ax,es:[di]是错误的,mov ax,[es:di]是正确的。mov word [var],2是正确的。mov eax,[ebx*2+ecx+offset]正确

NASM 使用跟 MASM 不同的浮点寄存器名:MASM 叫它们'ST(0)','ST(1)'等,而'a86'叫它们'0','1'等,NASM 则叫它们'st0','st1'等。

'tag resb 64',读作"保留 64 字节" 声明未初始化的数据。

NASM 使用反斜线(\)作为续行符;如果一个以一个反斜线结束,那第二行会被认为是前面一行的一部分。多用于字符串吧。

labels 中的有效的字符是字母,数字,'-','$','#','@','~','.'和'?'。但只有字母'.',(具有特殊含义,参阅 3.9),'_'和'?'可以作为标识符的开头。一个标识符还可以加上一个'$'前缀,以表明它被作为一个标识符而不是保留字来处理。这样的话,如果你想到链接进来的其他模块中定义了一个符号叫'eax',你可以用'$eax'在NASM 代码中引用它,以和寄存器的符号区分开。

`INCBIN':包含其他二进制文件。
'INCBIN'是从老的 Amiga 汇编器 DevPac 中借过来的:它将一个二进制文件逐字逐句地
包含到输出文件中。这能很方便地在一个游戏可执行文件中包含中图像或声音数
据。它可以以下三种形式的任何一种使用:
incbin "file.dat" ; include the whole file
incbin "file.dat",1024 ; skip the first 1024 bytes
incbin "file.dat",1024,512 ; skip the first 1024, and
; actually include at most 512

message db 'hello, world'
msglen equ $-message

buffer: db 'hello, world'
yes: times 64-$+buffer db ' '

'jmp $'来表示无限循环。

'$$'计算当前段开始处的地址,所以你可以通过($-$$)找出你当前在段内的偏移。

相当实用

'/'是无符号除,'//'是带符号除。同样的,'%'和'%%'提供无符号与带符号的模运算。

第一遍汇编是用于确定所有的代码与数据的尺寸大小,这样的话,在第二遍产生代码的时候,就可以知道代码引用的所有符号地址。所以,有一件事NASM 不能处理,那就是一段代码的尺寸依赖于另一个符号值,而这个符号又在这段代码的后面被声明。比如:
times (label-$) db 0
label: db 'Where am I?'

在前面可以,后面不行。

'EXTERN'操作符可以带有任意多个参数,每一个都是一个符号名:extern _sscanf,_fscanf

'GLOBAL'使用跟'EXTERN'相同的语法,除了它所引用的符号必须在同一样模块中已经被
定义过了,比如:
global _main

C 编译器对所有的全局符号(函数或数据)的名字有一个转化,它们被定义为在名字前面加上一个下划线,就象在 C 程序中出现的那样。所以,比如,一个 C 程序的函数'printf'对汇编语言程序中来说,应该是'_printf'。你意味着在你的汇编程序中,你可以定义前面不带下划线的符号,而不必担心跟 C 中的符号名产生冲突,但是asm文件本身不用吧

对于汇编链接,必须使用C语言的东西,如果上C语言,那么就可以链接了,因为只要我写的转义成nasm代码就可以了。

联立两个纯bin文件是不行的。

使用’bin'格式来产生`.EXE'文件。
'.EXE'文件是相当简单的,所以可以通过编写一个纯二进制文件然后在前面
连接上一个 32bytes 的头就可以产生一个'.exe'的文件了。这个文件头也是
相当简单,它可以通过使用 NASM 自己的'DB'和'DW'命令来产生,所以你可以使
用'bin'输出格式直接产生'.EXE'文件。
在 NASM 的包中,有一个'misc'子目录,这是一个宏文件'exebin.mac'。它定义
了三个宏`EXE_begin',`EXE_stack'和`EXE_end'.
要通过这种方法产生一个'.EXE'文件,你应当开始的时候先使用'%include'载
入'exebin.mac'宏包到你的源文件中。然后,你应当使用'EXE_begin'宏(不带
任何参数)来产生文件头数据。然后像平常一样写二进制格式的代码-你可以
使用三种标准的段'.text','.data','.bss'.在文件的最后,你应当调用
'EXE_end'宏(还是不带任何参数),它定义了一些标识段 size 的符号,而这些宏
会由'EXE_begin'产生的文件头代码引用。
在这个模块中,你最后的代码是写在'0x100'开始的地址处的,就像是'.COM'文
件-实际上,如果你剥去那个 32bytes 的文件头,你就会得到一个有效的'.COM'程
序。所有的段基址是相同的,所以程序的大小被限制在 64K 的范围内,这还是跟
一个'.COM'文件相同。'ORG'操作符是被'EXE_begin'宏使用的,所以你不必自己
显式的使用它
你可以直接使用你的段基址,但不幸的是,因为这需要在文件头中有一个重定
位,事情就会变得更复杂。所以你应当从'CS'中拷贝出一个段基址。
进入你的'.EXE'文件后,'SS:SP'已经被正确的指向一个 2Kb 的栈顶。你可以通过
调用'EXE_stack'宏来调整缺省的 2KB 的栈大小。比如,把你的栈 size 改变到
64bytes,你可以调用'EXE_stack 64'
一个关于以这种方式产生一个'.EXE'文件的例子在 NASM 包的子目录'test'中,
名字是'binexe.asm'

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值