使用汇编语言的TCC Hello世界?

时间:2013-11-18 19:11:13

标签: assembly tcc

我不懂汇编语言,在我的学校,他们只是为了展示汇编语言和编译方式。

你们可以使用可以用tccasm运行的汇编语言给我一些基本的hello world示例吗?

任何帮助表示赞赏

1 个答案:

答案 0 :(得分:1)

这是一个32位的Windows hello世界:

.global  main

.section .text
main:
    leal    message, %eax
    pushl   %eax // the C convention is params are pushed onto the stack
    call    printf
    popl    %eax // and the caller is responsible for cleanup
    pushl   $0
    call    exit
    hlt // never reached
.data
message:
    .string  "Hello, world!\n\0"

使用此构建:tcc test.s -lmsvcrt(文件名必须以.s结尾,以便tcc将其识别为asm文件)

调用C函数来完成工作。您也可以只使用Windows功能:

.global  main

.section .text
main:
    pushl $-11 // STD_OUTPUT_HANDLE
    call GetStdHandle // the return value will be in eax

    // now we'll call WriteFile. Args are pushed from right to left
    pushl $0 // lpOverlapped == null, don't want async
    pushl $0 // lpNumberOfBytesWritten == null, we don't care
    pushl $14 // nNumberOfBytesToWrite, our hello world has 14 chars.
    leal message, %ebx // load address for lpBuffer, pointer to the string to write
    pushl %ebx // and push it to the stack
    pushl %eax // the return value we got from GetStdHandle
    call WriteFile // and write the file
    // unlike the C convention, the Windows functions clean up their own stack
    // so we don't have to pop that stuff

    // and now we'll call ExitProcess to get out
    pushl   $0 // our main's return value of 0 == success
    call    ExitProcess
    hlt // never reached
.data
message:
    .string  "Hello, world!\n\0"// so we don't have to pop that stuff

// and now we'll call ExitProcess to get out
    pushl   $0
    call    ExitProcess
    hlt // never reached
.data
message:
    .string  "Hello, world!\n\0"

这里不需要C lib,所以用简单的tcc test.s构建,当你从控制台运行它时,你应该在那里看到消息。

有趣的事实:Windows功能很容易使用,你可以简单地弹出一个消息框:

.global  main

.section .text
main:
    pushl $0 // MB_OK
    pushl $0 // title = null (will use the default of "Error")
    leal message, %eax // load our message
    pushl %eax // and push the string pointer to the argument list
    pushl $0 // hwnd == null, no owning window
    call MessageBoxA // and pop up the message box
    pushl   $0
    call    ExitProcess
    hlt // never reached
.data
message:
    .string  "Hello, world!\n\0" // don't forget the zero terminator!

MessageBoxA位于user32中,因此使用tcc test.s -luser32进行构建,运行即可。

这都是win32,因为我不知道很多win64,但32位程序仍然可以正常工作,你可以玩它。 tcc使用AT& T汇编语法,虽然不常见,但要将nasm或大多数其他汇编程序的Intel语法转换为它,请记住:

  • 它需要指令的长度后缀。推送一个长的,即32位的值时,pushl代替push

  • immediates,数字文字,以$为前缀。实际上,现在我写这篇文章,我意识到我可以写上pushl $message而不是两步leal message, %eax pushl %eax。哦,两种方式都有效。但是如果你忘记$,它会尝试将它用作指针,并且在加载东西时你很可能会在看起来很小的内存地址上看到非法的读/写。

  • 注册名称需要%前缀

  • 它是源,目标,与英特尔语法的目标源相反。 (我学习了作为newb的英特尔方式,所以AT& T语法对我来说很落后!)

但是如果你还记得这四个差异,你可以很容易地将英特尔语法代码翻译成tcc的AT& T语法代码。一个微小的变化是tcc使用C样式注释(// comment),而大多数其他汇编程序使用; command

tcc的另一个问题是你不必声明extern函数,也不必使用参数length suffix或underscore prefix。你写它几乎就像用C编写的那样,虽然ASCII或Wide后缀需要在那里(那些是C中的宏; #define MessageBox MessageBoxA所以在Windows标题中,如果用unicode编译则更换A为W支持。区别在于A版本采用ascii字符串 - 每个字符8位,不能访问所有字符,W版本采用16位unicode字符串。)。

附注:Win32函数的实际受损名称类似于_MessageBoxA @ 16。您可以看到我们在示例代码中使用了'A',正如我刚才提到的,但不是_也不是@ 16。名称的这些位在C中是隐藏的,用于帮助捕获错误数量的参数 - @ 16表示它需要16个字节的参数,对于32位的消息框,这是hwnd(4,HWND),指向消息的指针( 4,char *),指向标题(4,char *)的指针,以及标志(4,一个int)。如果你看到互联网上的示例代码调用具有这些变化的函数,那就是它存在的原因,并且你不需要它与tcc。

那应该让你开始吧!