如何获取 nasm 中系统调用 getcwd 返回字符串的真实长度?
我的程序调用中断80h的函数183(getcwd),它将当前工作目录的绝对路径名复制到buff指向的内存位置,其长度为4096。返回的绝对路径名长度通常小于4096字节,所以我想得到它的真实长度。我怎样才能做到这一点?
%define LF 0Ah ; Line feed ASCII code.
%define STDOUT_FILENO 1 ; Standard output stream.
%define SYS_exit 1
%define SYS_write 4
%define SYS_getcwd 183
SECTION .bss
buff resb 4096
SECTION .text
global _start
_start:
mov eax, SYS_getcwd ; getcwd
mov ebx, buff
mov ecx, 4096
int 80h
mov eax, SYS_write ; print result to stdout
mov ebx, STDOUT_FILENO
mov ecx, buff
mov edx, 4096
int 80h
mov eax, SYS_exit ; exit
mov ebx, 0
int 80h
我添加代码来查找以空结尾的字符串的长度到我的程序中,如下所示,它可以工作:
%define LF 0Ah ; Line feed ASCII code.
%define STDOUT_FILENO 1 ; Standard output stream.
%define SYS_exit 1
%define SYS_write 4
%define SYS_getcwd 183
SECTION .data
mesg1 db "Can't not find string length.",LF
mesg1_l db $-mesg1
SECTION .bss
buff resb 4096
SECTION .text
global _start
_start:
mov eax, SYS_getcwd ; getcwd
mov ebx, buff
mov ecx, 4096
int 80h
mov al, 0 ; find string length with scasb
mov edi, buff
cld
repne scasb
jne error1
sub ecx, 4096
neg ecx
mov edx,ecx
print: mov byte [buff + ecx],LF
mov byte [buff + ecx + 1], 0
inc edx
mov eax, SYS_write ; print result to stdout
mov ebx, STDOUT_FILENO
mov ecx, buff
int 80h
jmp exit
error1: mov eax, SYS_write
mov ebx, STDOUT_FILENO
mov ecx, error1
mov edx, mesg1_l
int 80h
exit: mov eax, SYS_exit ; exit
mov ebx, 0
int 80h
My program calls function 183 (getcwd) of interrupt 80h which copies an absolute pathname of the current working directory to the memory location pointed to by buff, which is of length 4096. Returned absolute pathname length is usually less than 4096 bytes so i want to get its true length. How can i do that?
%define LF 0Ah ; Line feed ASCII code.
%define STDOUT_FILENO 1 ; Standard output stream.
%define SYS_exit 1
%define SYS_write 4
%define SYS_getcwd 183
SECTION .bss
buff resb 4096
SECTION .text
global _start
_start:
mov eax, SYS_getcwd ; getcwd
mov ebx, buff
mov ecx, 4096
int 80h
mov eax, SYS_write ; print result to stdout
mov ebx, STDOUT_FILENO
mov ecx, buff
mov edx, 4096
int 80h
mov eax, SYS_exit ; exit
mov ebx, 0
int 80h
I add code to find length of null terminated string to my program as following and it works:
%define LF 0Ah ; Line feed ASCII code.
%define STDOUT_FILENO 1 ; Standard output stream.
%define SYS_exit 1
%define SYS_write 4
%define SYS_getcwd 183
SECTION .data
mesg1 db "Can't not find string length.",LF
mesg1_l db $-mesg1
SECTION .bss
buff resb 4096
SECTION .text
global _start
_start:
mov eax, SYS_getcwd ; getcwd
mov ebx, buff
mov ecx, 4096
int 80h
mov al, 0 ; find string length with scasb
mov edi, buff
cld
repne scasb
jne error1
sub ecx, 4096
neg ecx
mov edx,ecx
print: mov byte [buff + ecx],LF
mov byte [buff + ecx + 1], 0
inc edx
mov eax, SYS_write ; print result to stdout
mov ebx, STDOUT_FILENO
mov ecx, buff
int 80h
jmp exit
error1: mov eax, SYS_write
mov ebx, STDOUT_FILENO
mov ecx, error1
mov edx, mesg1_l
int 80h
exit: mov eax, SYS_exit ; exit
mov ebx, 0
int 80h
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
问:如何查找字符串(例如“getcwd()”返回的字符串)的长度?
答:与标准库函数“strlen()”的做法相同:解析字符串直到找到“\0”分隔符,然后返回该位置作为字符串长度。
附:
我强烈建议您考虑使用 Gnu Assembler“gas”而不是“nasm”。一旦您开始使用 x86 以外的汇编器,“bass-ackwards”Intel 语法就会变得非常烦人。
恕我直言 ...
Q: How do I find the length of a string (e.g. the string returned by "getcwd()")?
A: The same way the standard library function "strlen()" would do it: parse the string until you find a '\0' delimiter, then return that position as the string length.
PS:
I'd strongly urge you to consider using Gnu Assembler "gas" instead of "nasm". As soon as you start playing with assemblers other than x86, the "bass-ackwards" Intel syntax gets really annoying.
IMHO ...
我认为您的 strlen 例程(scasb)可以在 ecx = -1 下工作,但在 ecx = 4096 下则不行。尝试一下。
编辑:我没有注意到你减去了 4096。这应该可以。对不起。
我注意到“getcwd”有点“有趣”。它是一个系统调用,但出现在“man 3”中,而不是预期的“man 2”中。不知道为什么。
最好的,
坦率
Your strlen routine (scasb) would work with ecx = -1, but not with ecx = 4096 I think. Try that.
Edit: I didn't notice that you subtracted 4096. That should work. Sorry.
I notice that "getcwd" is kinda "funny". It is a system call, but appears in "man 3", not "man 2" as expected. No idea why.
Best,
Frank
这不是对你的问题的回答;这是一个提醒,您不应该自己进行系统调用。即使您坚持使用汇编语言进行编程(为什么?),您也应该让 C 库为您进行系统调用,因为:
sysenter
或syscall
而不是int
。所有系统调用都可以作为常规的旧 C 函数使用。下面是经过调整以正确执行此操作的程序:(
main
顶部的垃圾确保 16 字节堆栈指针对齐,这是 ABI 所要求的。)This is not an answer to your question; it is a reminder that you should not make system calls yourself. Even if you insist on programming in assembly (why?) you should let the C library make system calls for you, because:
errno
.sysenter
orsyscall
rather thanint
when possible.All the system calls are available as regular old C functions. Here's your program adjusted to do this properly:
(The gunk at the top of
main
ensures 16-byte stack pointer alignment, which is required by the ABI.)