.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"
.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
.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!
1条答案
按热度按时间kx7yvsdv1#
下面是一个32位的Windows Hello World:
字符串
用这个构建:
tcc test.s -lmsvcrt
(文件名必须以.s结尾,以便tcc将其识别为asm文件)它调用C函数来完成这项工作。您也可以只使用Windows功能:
型
这里不需要C库,所以用一个简单的
tcc test.s
构建,当你从控制台运行它时,你应该在那里看到消息。有趣的事实:Windows功能很容易使用,你可以弹出一个消息框,简单到足以:
型
MessageBoxA在user 32中找到,因此使用
tcc test.s -luser32
构建,运行,您将得到它。这都是win32,因为我不知道很多win 64,但32位程序应该仍然工作得很好,你可以玩它。tcc使用AT&T汇编语法,这并不常见,但要将nasm或大多数其他汇编程序的Intel语法转换为它,请记住:
pushl
而不是push
。pushl $message
而不是两步leal message, %eax pushl %eax
。哦,好吧,两种方式都起作用。但是如果你忘记了$,它会试图将其用作指针,当加载东西时,你很可能会看到在小内存地址上的非法读/写。但是如果您记住这四个区别,您可以相当容易地将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。
这应该让你开始!