Linux 汇编;参数列表失控

发布于 2024-11-30 17:38:57 字数 2899 浏览 0 评论 0原文

我对任何类型的汇编编程都很陌生,而且因为我听说 Linux 的 NASM 类型汇编比基于 DOS 的汇编相对简单,所以我决定尝试一下。

到目前为止,这是我的程序:

section .data
    opening:    db  'Opening file...',10
    openingLen: equ $-opening
    opened:     db  'File opened.',10
    openedLen:  equ $-opened
    bad_params: db  'Usage: writeFile filename.ext',10
    bad_paramsLen:  equ $-bad_params
    not_opened: db  'Unable to open file.  Halted.',10
    not_openedLen:  equ $-not_opened
    hello:      db  'Hello, this is written to a file'
    helloLen:   equ $-hello
    success:    db  'Successfully wrote to file.',10
    successLen: equ $-success

section .bss
    file:       resd    1

section .text
    global _start:

_start:
    pop ebx             ; pop number of params
    test ebx,2          ; make sure there are only 2
    jne bad_param_list
    pop ebx

    mov eax,4           ; write out opening file msg
    mov ebx,1
    mov ecx,opening
    mov edx,openingLen
    int 80h

    mov eax,5           ; open file
    pop ebx
    mov ecx,64 
    mov edx,777o            ; permissions of file
    int 80h
    mov dword [file],eax

    test dword [file],0
    jle bad_open

    mov eax,4           ; write successful open message
    mov ebx,1
    mov ecx,opened
    mov edx,openedLen
    int 80h

    mov ebx,file            ; write to file (4 already in eax)
    mov ecx,hello
    mov edx,helloLen
    int 80h

    mov eax,6           ; close file
    mov ebx,file
    int 80h

    mov eax,4           ; write successfully written msg
    mov ebx,1
    mov ecx,success
    mov edx,successLen
    int 80h

    mov eax,1           ; exit
    mov ebx,0
    int 80h

bad_param_list:
    mov eax,4           ; write that params are bad
    mov ebx,1
    mov ecx,bad_params
    mov edx,bad_paramsLen
    int 80h

    mov eax,1           ; exit with code 1
    mov ebx,1
    int 80h

bad_open:
    mov eax,4           ; write that we couldn't open the file
    mov ebx,1
    mov ecx,not_opened
    mov edx,not_openedLen
    int 80h

    mov eax,1           ; exit with code 2
    mov ebx,2
    int 80h

目标是将一串文本写入没有库函数的文件;我只使用 Linux 内核。我遇到了一些问题,比如到处缺少括号,以及所有其他错误,这些错误都是你从菜鸟到汇编所期望的,但我认为现在这基本上已经得到控制。

这是我的问题:据我所知,该程序的前四行应该将参数数量从堆栈中弹出,如果不仅有一个参数(除了程序名称),则跳转到 bad_param_list ,并将程序名称从堆栈中弹出。

但事实并非如此。下面是一些示例 I/O,为了清晰起见,重新格式化了:

$./writeFile
Opening file...
Unable to open file.  Halted.

$./writeFile x
Usage:  writeFile filename.ext

$./writeFile x x
Usage:  writeFile filename.ext

$./writeFile x x x
Opening file...
Unable to open file.  Halted.

$./writeFile x x x x
Opening file...
Unable to open file.  Halted.

$./writeFile x x x x x
Usage:  writeFile filename.ext

$./writeFile x x x x x x
Usage:  writeFile filename.ext

我注意到,如果您采用包括程序名称在内的参数数量,除以 2,并丢弃小数,如果答案是奇数,您将收到我的使用错误,但如果答案是偶数,您将收到无法打开错误。至少 10 个参数之前都是如此!

我到底是怎么做到这一点的?以及如何让它达到预期的结果?

I'm new to programming in any sort of assembly, and since I've heard that NASM-type assembly for Linux is comparatively simple to DOS based assembly, I decided to give it a try.

This is my program thus far:

section .data
    opening:    db  'Opening file...',10
    openingLen: equ $-opening
    opened:     db  'File opened.',10
    openedLen:  equ $-opened
    bad_params: db  'Usage: writeFile filename.ext',10
    bad_paramsLen:  equ $-bad_params
    not_opened: db  'Unable to open file.  Halted.',10
    not_openedLen:  equ $-not_opened
    hello:      db  'Hello, this is written to a file'
    helloLen:   equ $-hello
    success:    db  'Successfully wrote to file.',10
    successLen: equ $-success

section .bss
    file:       resd    1

section .text
    global _start:

_start:
    pop ebx             ; pop number of params
    test ebx,2          ; make sure there are only 2
    jne bad_param_list
    pop ebx

    mov eax,4           ; write out opening file msg
    mov ebx,1
    mov ecx,opening
    mov edx,openingLen
    int 80h

    mov eax,5           ; open file
    pop ebx
    mov ecx,64 
    mov edx,777o            ; permissions of file
    int 80h
    mov dword [file],eax

    test dword [file],0
    jle bad_open

    mov eax,4           ; write successful open message
    mov ebx,1
    mov ecx,opened
    mov edx,openedLen
    int 80h

    mov ebx,file            ; write to file (4 already in eax)
    mov ecx,hello
    mov edx,helloLen
    int 80h

    mov eax,6           ; close file
    mov ebx,file
    int 80h

    mov eax,4           ; write successfully written msg
    mov ebx,1
    mov ecx,success
    mov edx,successLen
    int 80h

    mov eax,1           ; exit
    mov ebx,0
    int 80h

bad_param_list:
    mov eax,4           ; write that params are bad
    mov ebx,1
    mov ecx,bad_params
    mov edx,bad_paramsLen
    int 80h

    mov eax,1           ; exit with code 1
    mov ebx,1
    int 80h

bad_open:
    mov eax,4           ; write that we couldn't open the file
    mov ebx,1
    mov ecx,not_opened
    mov edx,not_openedLen
    int 80h

    mov eax,1           ; exit with code 2
    mov ebx,2
    int 80h

The goal is to write a string of text to a file without library functions; I'm only using the Linux kernel. I had a few problems with missing brackets here and there, and all the rest of mistakes that you'd expect from a noob to assembly, but I think this is mostly under control now.

Here's my issue: From what I know, the first four lines of this program should pop the number of arguments off the stack, jump to bad_param_list if there is not only one parameter (aside from the program name), and pop the program name off the stack.

But this is not what happens. Here's some sample I/O, reformatted for clarity:

$./writeFile
Opening file...
Unable to open file.  Halted.

$./writeFile x
Usage:  writeFile filename.ext

$./writeFile x x
Usage:  writeFile filename.ext

$./writeFile x x x
Opening file...
Unable to open file.  Halted.

$./writeFile x x x x
Opening file...
Unable to open file.  Halted.

$./writeFile x x x x x
Usage:  writeFile filename.ext

$./writeFile x x x x x x
Usage:  writeFile filename.ext

What I've noticed is that if you take the number of arguments including the name of the program, divide by 2, and discard the decimal, if the answer is odd, you'll get my usage error, but if the answer is even, you'll get the unable to open error. This is true up until at least 10 arguments!

How the heck did I manage to do this? And how do I get it to have the expected result?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

迷鸟归林 2024-12-07 17:38:57

test ebx,2

除了设置标志之外,您

cmp ebx,2

希望test 在参数之间执行按位 AND 并丢弃结果。因此,如果两个参数在匹配的位置上没有 1 位,则特别会设置 ZF。 (在您的特定情况下,这相当于将 ZF 设置为 ebx 的倒数第二位的补码)。

相反,cmp 减去其参数并在设置标志后丢弃结果。在这种情况下,如果两个参数相等,则将设置 ZF。

Instead of

test ebx,2

you want

cmp ebx,2

test performs a bitwise AND between the arguments and throws the result away, except for setting the flags. So, in particular ZF will be set if the two arguments have no 1-bits in positions that match. (In your particular case, this works out as setting ZF to the complement of the second-to-lowest bit of ebx).

Conversely cmp subtracts its arguments and throws away the result after setting flags. In that case, ZF will be set if the two arguments are equal.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文