assembly 你好,世界,TCC使用汇编语言?

ahy6op9u  于 2023-08-06  发布在  其他
关注(0)|答案(1)|浏览(101)

我不懂汇编语言,在我的学校,他们这样做只是为了展示什么是汇编语言以及如何编译。
你们能给予我一些基本的hello world的例子,使用汇编语言,可以运行tccasm?
感谢任何帮助

kx7yvsdv

kx7yvsdv1#

下面是一个32位的Windows Hello World:

.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


这里不需要C库,所以用一个简单的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在user 32中找到,因此使用tcc test.s -luser32构建,运行,您将得到它。
这都是win32,因为我不知道很多win 64,但32位程序应该仍然工作得很好,你可以玩它。tcc使用AT&T汇编语法,这并不常见,但要将nasm或大多数其他汇编程序的Intel语法转换为它,请记住:

  • 它需要指令上的长度后缀。所以当推送一个长的,也就是32位的值时,是pushl而不是push
  • 立即数、数字文字以$为前缀。实际上,现在我写了这个,我意识到我可以写上面的pushl $message而不是两步leal message, %eax pushl %eax。哦,好吧,两种方式都起作用。但是如果你忘记了$,它会试图将其用作指针,当加载东西时,你很可能会看到在小内存地址上的非法读/写。
  • 寄存器名称需要前缀%
  • 它是源,目的地,这与英特尔语法的目的地,源相反。(我作为一个新手学习了英特尔的方式,所以AT&T的语法对我来说感觉很落后!)

但是如果您记住这四个区别,您可以相当容易地将Intel语法代码转换为tcc的AT&T语法代码。一个微小的变化是tcc使用C风格的注解(// comment),而大多数其他汇编器使用; command
tcc的另一个特点是你不需要声明外部函数,也不需要使用参数长度后缀或下划线前缀。你写它几乎像在C,虽然ASCII或宽后缀需要在那里(这些是宏在C; #define MessageBox MessageBoxA等,如果你在编译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。
这应该让你开始!

相关问题