汇编语言helloworld

目录

​编辑

0x0 汇编语言的用途

0x1 存在操作系统

C语言版本hello world

汇编语言版本hello world

Linux amd64架构发行版

Intel风格

AT&T风格

0x2 不存在操作系统

0x3 结语


0x0 汇编语言的用途

1. 深入理解计算机架构:汇编语言直接操作底层硬件,帮助理解计算机如何执行指令和管理内存。

2. 优化性能:汇编语言允许直接控制计算机资源,可以编写高效的代码以提高程序性能。

3. 嵌入式系统开发:许多嵌入式系统需要使用汇编语言进行编程,因为它可以更好地控制设备和资源。

4. 逆向工程:汇编语言是理解和修改二进制程序的关键工具,对于逆向工程和安全研究非常有用。

5. 扩展其他语言:了解汇编语言可以帮助理解高级语言的底层运行原理,有助于更好地编写和优化高级代码。

        学习汇编语言可以增强对计算机系统的理解,并为深入研究计算机科学领域打下坚实的基础。下面我带大家了解一下在X86架构中有操作系统和没有操作系统也就是裸机状态下汇编语言输出hello world的方法。以下都是Linux环境。

0x1 存在操作系统

C语言版本hello world

        C语言写一个hello world程序应该说是非常简单,每一个C语言工程师第一个C程序基本都类似于如下形式。

#include <stdio.h>

int main(int argc, char *argv[])
{
    printf("Hello world!\n");
    return 0;
}

在Linux amd64架构发行版中可以用以下命令编译运行

$ gcc -o hello hello.c
$ ./hello
Hello world!

汇编语言版本hello world

        由于汇编语言是一种贴近底层硬件的语言,所以汇编语言的hello world程序版本不单一,会因为环境的不同而不同,下面的汇编程序都是在Ubuntu 16.04发行版中正常编译运行的汇编语言hello world程序。值得注意一点是汇编语言的代码风格一般有Intel和AT&T格式,Intel风格的代码使用nasm编译,AT&T风格的代码使用gcc编译,一下是两种风格的代码。

Linux amd64架构发行版

Intel风格

; hello.asm
; ----------------------------------------------------------
        [bits 64]
    	global  _start

        section .text
_start:
        ; write(1, message, 13)
        mov     rax, 1                  ; 1 号系统调用是写操作 
        mov     rdi, 1                  ; 1 号文件系统调用是标准输出 
        mov     rsi, message            ; 输出字符串的地址 
        mov     rdx, 13                 ; 字符串的长度 
        syscall                         ; 调用系统执行写操作 

        ; exit(0)
        mov     rax, 60                 ; 60 号系统调用是退出 
        xor     rdi, rdi                ; 0 号系统调用作为退出 
        syscall                         ; 调用系统执行退出 
message:
        db      "Hello, World", 10      ; 注意到最后的换行 
$ nasm hello.asm && ./a.out
Hello, World

AT&T风格

// hello.S
// ---------------------------------------------------
        .section .text
        .global  main
main:
        movq     $1, %rax
        movq     $1, %rdi
        movq     $message, %rsi
        movq     $14, %rdx
        syscall

        movq     $60, %rax
        xorq     %rdi, %rdi
        syscall
	.section .data
message:
        .string      "Hello, World!\n"
$ gcc hello.S && ./a.out
Hello, world!

        这两个程序功能完全一致,只是代码风格有所不同,仔细观察代码也很容易能发现这些不一样的地方。在Linux中,内核提供一些操作的接口给用户态的程序使用,这就是系统调用。对于用户态的程序,其调用相应的接口的方式,是一条汇编指令syscall,代码中使用syscall指令进行系统函数的调用,从而实现字符串输出的效果,调用哪一个函数通过rax寄存器指定,这个数值可以从syscall table中获取,这是存在操作系统的情况下的汇编语言输出hello world的代码,下面演示一下如何在没有操作系统情况下也就是裸机状态下使用汇编语言输出hello world的方法,对于想自己开发内核的朋友来说,这应该是你会写到的第一个程序,对这部分不感兴趣的朋友,可以略过。。。

0x2 不存在操作系统

        当不存在操作系统的时候我们就没有办法使用syscall指令了,因为裸机状态下没有syscall指令和syscall table。但是裸机状态下因为没有操作系统的约束,我们就获得了整个计算机硬件资源的控制权限,也就是说你想干嘛就干嘛。在x86架构中有一块内存区域,当你向这个区域的指定位置写入特定的值,它就会在屏幕上输出该内容,裸机状态下我们有两种方法去控制屏幕的输出,一个是直接写内存,另一个是使用BIOS调用。裸机状态下想要执行一个程序的步骤比较麻烦并且需要一些特定条件,比如“一台裸机电脑”。。。当然我们可以选择替代方案,那就是虚拟机,用虚拟机来模拟一台PC,就不需要真的在物理机上进行试验了。这部分内容可以看我博客园的文章0X0    0X1。这两篇文章介绍了如何在裸机状态下通过直接写内存实现字符串输出,通过BIOS调用去实现的代码我放在下面,只需要把上面文章给到的代码改成下面的就好了。

org 0x7c00

mov ax, cs
mov ds, ax
mov es, ax

call dispstr
jmp $

dispstr:
    mov ax, 0x1301
    mov bx, 0x000c
    mov cx, 10
    mov dx, 0x1010
    mov bp, BootMessage
    int 0x10
    ret

BootMessage: db "hello!", 0

times 510-($-$$) db 0
dw 0xaa55

        代码都是用nasm编译的也都是Intel风格,感兴趣的朋友可以自行研究一下,这里就不写了,如果想使用gcc,那步骤更复杂一些,还要写链接脚本,这部分需要的就自行研究吧,有时间的话我可能会写一篇这个的博文,现在暂时如此。。。

0x3 结语

        汇编语言还是值得研究的,也非常有趣,想深入计算机原理的必学技能,上面的汇编指令都是x86指令集的,arm指令集区别比较大,不过会了一种再去学另一种也并不困难,深入研究汇编多写写裸机程序,对理解计算机原理我觉得是很有帮助的。写汇编程序要非常的细心,错一个字节就很有可能让整个程序崩溃。。。这就是关于汇编语言输出字符串的内容了,个人拙见,欢迎指正!

  • 18
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值