我开始学习汇编程序,我在Unix工作。我想打开一个文件并在上面写上“Hello world”。
section.data
textoutput db 'Hello world!', 10
lentext equ $ - textoutput
filetoopen db 'hi.txt'
section .text
global _start
_start:
mov eax, 5 ;open
mov ebx, filetoopen
mov ecx, 2 ;read and write mode
int 80h
mov eax, 4
mov ebx, filetoopen ;I'm not sure what do i have to put here, what is the "file descriptor"?
mov ecx, textoutput
mov edx, lentext
mov eax, 1
mov ebx, 0
int 80h ; finish without errors
但是当我编译它时,它什么也没做。我究竟做错了什么? 当我打开一个文件,文件描述符值返回哪里?
答案 0 :(得分:15)
这是x86 Linux(x86不是唯一的汇编语言,Linux不是唯一的Unix!)...
section .data
textoutput db 'Hello world!', 10
lentext equ $ - textoutput
filetoopen db 'hi.txt'
文件名字符串需要一个0字节的终结符:filetoopen db 'hi.txt', 0
section .text
global _start
_start:
mov eax, 5 ;open
mov ebx, filetoopen
mov ecx, 2 ;read and write mode
2
是O_RDWR
系统调用的open
标志。如果您希望创建该文件(如果该文件尚不存在),您还需要O_CREAT
标志;如果指定O_CREAT
,则需要第三个参数,即文件的权限模式。如果你在C标题中徘徊,你会发现O_CREAT
定义为0100
- 小心前导零:这是一个八进制常量!您可以使用nasm
后缀在o
中编写八进制常量。
所以你需要像mov ecx, 0102o
这样的东西来获得正确的旗帜,mov edx, 0666o
来设置这些权利。
int 80h
来自系统调用的返回码在eax
中传递。这里,这将是文件描述符(如果打开成功)或小负数,这是一个负errno
代码(例如,EPERM
为-1)。请注意,从原始系统调用返回错误代码的约定 not 与C syscall包装器完全相同(通常返回-1
并设置errno
误差)...
mov eax, 4
mov ebx, filetoopen ;I'm not sure what do i have to put here, what is the "file descriptor"?
...所以在这里你需要mov ebx, eax
首先(在覆盖open
之前保存eax
结果)然后mov eax, 4
。 (您可能想要先考虑检查结果是否为正,如果不是,则考虑以某种方式打开失败。)
mov ecx, textoutput
mov edx, lentext
此处缺少int 80h
。
mov eax, 1
mov ebx, 0
int 80h ; finish without errors
答案 1 :(得分:0)
这取决于您使用的汇编程序以及您是否希望使用C运行时。在这种情况下,似乎是来自rosettacode的Hello World文本示例,他们正在使用nasm。假设您有一个_start字段,则不需要C运行时,因此您将其组合到一个elf对象文件并将其链接到一个程序中:
nasm -felf hello.asm
ld hello.o -o hello
现在您可以运行hello
程序。
使用C运行时执行工作而不是linux系统调用的稍微可移植的示例可能如下所示。如果您按照描述进行链接,则可以使用printf
进行打印。
;;; helloworld.asm -
;;;
;;; NASM code for Windows using the C runtime library
;;;
;;; For windows - change printf to _printf and then:
;;; nasm -fwin32 helloworld.asm
;;; link -subsystem:console -out:helloworld.exe -nodefaultlib -entry:main
;;; helloworld.obj msvcrt.lib
;;; For gcc (linux, unix etc):
;;; nasm -felf helloworld.asm
;;; gcc -o helloworld helloworld.o
extern printf
section .data
message:
db 'Hello, World', 10, 0
section .text
global main
main:
push dword message ; push function parameters
call printf ; call C library function
add esp, 4 ; clean up the stack
mov eax, 0 ; exit code 0
ret
有关文件描述符的信息 - 请阅读open(2)
手册页或查看wikipedia。 posix是指一个开放的i / o流。在你的情况下,stdout。
答案 2 :(得分:0)
你读过Linux Assembly HOWTO了吗?它涵盖了你的问题。
您还可以使用gcc -S -fverbose-asm -O1
编译一些C代码并查看生成的程序集。
最后,我认为不值得为汇编程序打扰。编译器肯定会产生比你写的更好的代码。
答案 3 :(得分:0)
这是x64 Linux示例
; Program to open and write to file
; Compile with:
; nasm -f elf64 -o writeToFile64.o writeToFile64.asm
; Link with:
; ld -m elf_x86_64 -o writeToFile64 writeToFile64.o
; Run with:
; ./writeToFile64
;==============================================================================
; Author : Rommel Samanez
;==============================================================================
global _start
%include 'basicFunctions.asm'
section .data
fileName: db "testFile.txt",0
fileFlags: dq 0102o ; create file + read and write mode
fileMode: dq 00600o ; user has read write permission
fileDescriptor: dq 0
section .rodata ; read only data section
msg1: db "Write this message to the test File.",0ah,0
msglen equ $ - msg1
msg2: db "File Descriptor=",0
section .text
_start:
mov rax,2 ; sys_open
mov rdi,fileName ; const char *filename
mov rsi,[fileFlags] ; int flags
mov rdx,[fileMode] ; int mode
syscall
mov [fileDescriptor],rax
mov rsi,msg2
call print
mov rax,[fileDescriptor]
call printnumber
call printnewline
; write a message to the created file
mov rax,1 ; sys_write
mov rdi,[fileDescriptor]
mov rsi,msg1
mov rdx,msglen
syscall
; close file Descriptor
mov rax,3 ; sys_close
mov rdi,[fileDescriptor]
syscall
call exit