阅 读 文 章

Linux 的 x86 汇编程序设计

[来源:网上转载 () | 作者:网友() | 时间:2007-07-07 | 浏览:人次 ]

本质上来说, 这篇文章是把我最感兴趣的两样编程东西: Linux 操作系统和汇编语言程序设计结合在一起. 这两个都不(或者说应该不)需要介绍; 像 Win32 的汇编,Linux 的汇编运行在 32 位的保护模式下...但它又有一个截然不同的优势就是它允许你调用 C 的标准库函数和 Linux 的共享库函数. 我开始给 Linux 下的汇编语言编程来个简要介绍; 为了更好读一点, 你可能要跳过这个基本的小节.

编译和链接
---------------------
Linux 下两个最主要的汇编器是 Nasm(free, Netwide Assembler)和 GAS(free, Gnu Assembler),
后一个和 GCC 结合在一起. 在这篇文章里我将集中在 Nasm 上, 把 GAS 放在后面,因为它使用 AT&T 的语法, 需要一个长的介绍.
Nasm 调用时应该带上 ELF 格式选项("nasm -f elf hello.asm"); 产生的目标文件用GCC 来链接("gcc hello.o"), 产生最终的 ELF 二进制代码. 下面的这个脚本可用来编译 ASM 的模块; 我尽量把它写得简单, 所以所有它做的就是接受传给它的第一个文件名, 用 Nasm 编译, 用 GCC 来链接.
#!/bin/sh
# assemble.sh =========================================================
outfile=${1%%.*}
tempfile=asmtemp.o
nasm -o $tempfile -f elf $1
gcc $tempfile -o $outfile
rm $tempfile -f
#EOF =================================================================

基本知识:
----------
当然最好的就是在了解系统细节之前从一个例子开始. 这里是一个最基本的"hello-word" 形式的程序:
; asmhello.asm ========================================================
global main
extern printf
section .data
msg db "Helloooooo, nurse!",0Dh,0Ah,0
section .text
main:
push dword msg
call printf
pop eax
ret
; EOF =================================================================
纲要: "global main" 必须声明为全局的(global) -- 并且既然我们用 GCC 来链接,进入点必须以 "main" 来命名 -- 从而装入系统. "extern printf" 只是一个声明,为以后在程序中调用; 注意这是必须的; 参数的大小不需要声明. 我已经把这个例子用标准的 .data, .text 分节, 但这不是严格必须的 -- 可能只需要一个 .text段, 就像在 DOS 下一样.
在代码的主体部分, 你必须把参数压栈来传递给调用. 在 Nasm 里, 你必须声明所有不明确数据的大小; 因此就有 "dword" 这个限定词. 注意和其他汇编器一样,Nasm 假设所有的内存/标号的引用都指的是内存地址或者标号, 而不是它的内容.
因而, 指明字符串 msg 的地址, 你应该使用 push dword msg, 指明字符串 msg 的内容, 应该用 push dword [msg] (这只能包含 msg 的前四个字节). 因为 printf
需要一个指向字符串的指针, 我们应该指明 msg 的地址.
调用 printf 非常的直接. 注意每一次调用后你必须把栈清除(见下); 所以 PUSH 了一个
dword 后, 我从栈里把一个 dword POP 进一个无用的寄存器. Linux 程序只简单的用一个 RET 来返回系统, 由于每个进程都是 shell(或者是 PID)的产物, 所以程序结束后把 控制权还给它.
注意到在 Linux 下, 你是在 "API" 或中断服务的场所里使用系统带来的标准共享库.

所有的外部引用由 GCC 管理, 它给 asm 程序员节省了大部分的工作. 一旦你习惯了基本的技巧, Linux 下的汇编编程实际上要比 DOS 简单的多.

C 调用的语法
--------------------
Linux 使用 C 的调用模式 -- 意味着参数以相反的顺序进栈(最后一个最先), 调用者必须清
除栈. 你可以从栈里把值 pop 出来:
push dword szText
call puts
pop ecx
或者直接修改 ESP:
论坛热门帖子: [lch203] 写得蛮好的linux学习笔记(10-21)
[黑马制造] 学习java的30个目标(10-19)
[笑傲股林] 做测试半年了,有点迷茫,应该再学些什么提高自己的测试水平和测试能力呢?(10-19)
[udp8589] 大家用google的来吱一声? 用百度的~~也来报道下?(10-18)
[沂偌掳兆] 本人总结的一些认为C++比较经典的书籍,希望对大家有用(10-18)
TAG标签: 程序设计 汇编 调用 printf dword push 一个 ecx Linux

最新评论 共有0位网友发表了评论

发表评论

评论内容:不能超过250字,需审核,请自觉遵守互联网相关政策法规。
用户名:(注册)
密码:
验证码:
匿名发表

网站地图友情连接交流论坛网站投稿广告服务联系我们留言本站长统计
Some rights reserved: www.chmhome.com, 鄂ICP备07010232号 E-mail:chinakafei@live.com,QQ:552766
中国咖啡技术网(Chmhome):国外编程技术书籍,中文编程手册,经典编程文章,交流技术,技术软件下载,计算机论文,毕业论文.