4.1 80x86汇编编程-1
4.1.1 hello world-1
目录
Hello World
首先我们来看一下咱们 这个程序的主体 首先第一个吧 虽然我们没有详细的讲解过 一个完整的汇编程序的结构 但是从这张图上我们可以基本上 猜得出来看到程序入口地址在哪 -main 因为-main 是个int C里面的一个main C程序的入口函数是main 所以这个对应的汇编函数 它的入口地址也是main main里面我们看每行干了些什么事
首先看一下 第一行和第三行 push 后边一个move 这个完全非常熟悉了 因为它还是一个C程序吗 C程序函数被调用的时候 它的入口地方呢会建立这个栈帧 就是push ebp和mov esp到 ebp 这个我们非常的熟悉
那么当中这一行mov 16 到eax 是干什么的呢 这个我也不知道 这个我也不知道 我们回头看 后来这个代码会被优化掉
后来再往下走 再往下这一条指令 这是一条减法指令 把esp减8 那这个呐 我们应该也熟悉了 就是给当前main函数一个分配 8字节的一个栈空间 esp减8吗
那这个是干嘛的呢 后来又加了一个and 为什么会有一个与操作呢 实际上把esp跟负16去 与一下 的话 就使得什么 因为负16大家都知道 用补码表示的话 它的最低四位是0 全零 它跟esp 与一下的话 就确保这个栈顶地址是16字节对齐 这一般来说 在C程序里头 我们分配栈的话 一般来说 要保这个栈顶地址要16字节对齐 对一个函数而言 经常有这样的一个约定 但这个约定是一个软件约定 可以修改的
接下来两个call 对应两个函数 这两个函数都不认识 其实这两个呢 当然跟我们汇编编程 应该关系不是特别太大 这两个函数分别都是 与C运行时库初始化相关的 这大家知道就是说 我们写个C程序吧 一般来说 C程序默认去调的libc这个库 C运行时库 你所调的一些C调用 都是在C运行时库里实现的 那么这两个函数呢 关于C运行时库初始化相关的 其中第一个呢 跟栈的分配相关 这咱们就不展开说了 跟我们关系不是太大
再往下看 似成相识 因为我们在这个原来C代码里 就调了一个printf 最后在退出时 调了一个exit 0 exit 0 好说了 就是程序退出吗 就是程序退出这个调用 那么这样的话 相当于就是说 mov 0 括号esp 实际上就设置了这个exit 这个零的 这个参数 这我们回想一下 就相当于mov零到栈顶 然后call 返回地址压栈 就去进入exit 实际上这个地方就做了一个过程调用参数 而其我们看到就是说 call(exit)之后呢 renturn(0)那个代码 在这里头没有体现 为什么呢 已经调用了exit 编译前是很聪明的 exit之后 这个代码就不给你编译了 renturn(0)就给它skip掉了 虽然前面已经写了一个了
再往下看的话呢 call puts 注意啊 我们原来调的那个函数 叫call printf用的是printf 那这个地方呢 我认为这个编译器比较聪明 printf里头我们只是用了什么 把它输出一个字符串 没有做任何格式的转化 所以它用一个puts来替换 那这样简单一点了
然后这个呢 因为相当于就是说 我们要打个hello world出发 出来 所以puts唯一的一个参数 也就是说它要打印出来的 字符串的地址 所以我们就把这个地址 lc0放到栈顶callputsok然后就把这个helloworld可以打印出来了printf打印出来ok那么lc0表示什