交流
商城
MCN
登入
注册
首页
提问
分享
讨论
建议
公告
动态
发表新帖
发表新帖
1 第一个汇编程序
分享
未结
0
793
李延
LV6
2022-05-31
悬赏:20积分
# 1. 万物开始于 Hello, World! 我们第一个汇编语言同样开始于在控制台打印Hello, World! 。 # 2 . 通过c语言得到我们的汇编代码 首先我们写一个c语言的Hello, World。 ```c #include <stdio.h> int main() { printf("Hello, World!\n"); return 0; } ``` 使用gcc编译器 将上面的 c语言编译为汇编语言 ```c gcc -S -Og main.c ``` 得到原文如下: ```asm .file "main.c" .section .rodata.str1.1,"aMS",@progbits,1 .LC0: .string "Hello, World!" .text .globl main .type main, @function main: .LFB11: .cfi_startproc subq $8, %rsp .cfi_def_cfa_offset 16 movl $.LC0, %edi call puts movl $0, %eax addq $8, %rsp .cfi_def_cfa_offset 8 ret .cfi_endproc .LFE11: .size main, .-main .ident "GCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-44)" .section .note.GNU-stack,"",@progbits ``` 而其中很多行,以 `.` 开通的行都是助记符。帮助编译器进行编译工作。我们可以把这些内容删除掉,得到最简的汇编代码 ```asm .LC0: .string "Hello, World!" .globl main main: subq $8, %rsp movl $.LC0, %edi call puts movl $0, %eax addq $8, %rsp ret ``` # 3 编译为可运行的机器语言 gcc main.s -o main.out 执行 main.out 文件。我们就可以看到控制台打印Hello, World! # 4 解析代码 **globl** `.globl main` 表示 我们程序的入库,也就是主函数 **main:** 为我们函数的入库,也就是我们在c语言中写的main函数,后面的内容就是main函数的内容,直到 `ret` 返回。 **subq $8, %rsp** 表示寄存器rsp所指向的内存地址减少8个字节。rsp寄存器是栈 指针,这个动作表示入栈的操作,我们在后面章节讲到。同样`addq $8, %rsp`对于出栈。 **movl $.LC0, %edi** 将 $.LC0 的内容写入到寄存器edi中。我们可以看到LCO就是我们要打印的字符串的第一个字符地址。而edi 寄存器就是,表示 第一个参数。 **call puts** 调用 puts 函数,也就是输出函数。 **movl $0, %eax** 将 寄存器eax的值设为0. eax 就是保存函数返回值的寄存器。 **ret** 函数调用结束,返回。 我们逐步分析下来,发现基本逻辑与我们c语言的打印逻辑相同。区别在于,调用方法时,传参与返回值都时放到对应的寄存器中进行操作的。 比如调用printf函数时,我们首先是将参数保存在edi寄存器中,然后通过call调用printf。进入printf后,函数自己就会去edi寄存器中获取值。 同样 对于返回值,我们是保存在eax寄存器中,调用者就会去eax中去取返回值。
回帖
消灭零回复
提交回复
热议榜
java 相关知识分享
8
好的程序员与不好的程序员
6
写给工程师的十条精进原则
5
spring boot以jar包运行配置的logback日志文件没生成
5
一步一步分析SpringBoot启动源码(一)
5
MockMvc测试
5
【吐槽向】是不是有个吐槽的板块比较好玩
4
logstash jdbc同步mysql多表数据到elasticsearch
3
IntelliJ IDEA 优质License Server
3
.gitignore忽略规则
3
SpringBoot启动源码分析
3
一步一步分析SpringBoot启动源码(三)
3
2
一步一步分析SpringBoot启动源码(二)
2
积分不够将无法发表新帖
2
官方产品
Meta-Boot - 基于MCN
MCN - 快速构建SpringBoot应用
微信扫码关注公众号