我正在读一本书(汇编语言一步一步,使用Linux编程由Jeff Duntemann编写),我正在尝试更改显示该参数的程序,而不是显示环境变量。我试图只使用到目前为止所教的内容(没有C),并且我已经得到了打印环境变量的程序,但只有在我计算了我有多少并立即使用后,显然不满意。这就是我所拥有的:
global _start ; Linker needs this to find the entry point!
_start:
nop ; This no-op keeps gdb happy...
mov ebp,esp ; Save the initial stack pointer in EBP
; Copy the command line argument count from the stack and validate it:
cmp dword [ebp],MAXARGS ; See if the arg count exceeds MAXARGS
ja Error ; If so, exit with an error message
; Here we calculate argument lengths and store lengths in table ArgLens:
xor eax,eax ; Searching for 0, so clear AL to 0
xor ebx,ebx ; Stack address offset starts at 0
ScanOne:
mov ecx,0000ffffh ; Limit search to 65535 bytes max
mov edi,dword [ebp+16+ebx*4] ; Put address of string to search in EDI
mov edx,edi ; Copy starting address into EDX
cld ; Set search direction to up-memory
repne scasb ; Search for null (0 char) in string at edi
jnz Error ; REPNE SCASB ended without finding AL
mov byte [edi-1],10 ; Store an EOL where the null used to be
sub edi,edx ; Subtract position of 0 from start address
mov dword [ArgLens+ebx*4],edi ; Put length of arg into table
inc ebx ; Add 1 to argument counter
cmp ebx,44; See if arg counter exceeds argument count
jb ScanOne ; If not, loop back and do another one
; Display all arguments to stdout:
xor esi,esi ; Start (for table addressing reasons) at 0
Showem:
mov ecx,[ebp+16+esi*4] ; Pass offset of the message
mov eax,4 ; Specify sys_write call
mov ebx,1 ; Specify File Descriptor 1: Standard Output
mov edx,[ArgLens+esi*4] ; Pass the length of the message
int 80H ; Make kernel call
inc esi ; Increment the argument counter
cmp esi,44 ; See if we've displayed all the arguments
jb Showem ; If not, loop back and do another
jmp Exit ; We're done! Let's pack it in!
我将位移从第一个空指针移到[ebp+4+ebx*4] > [ebp+16+ebx*4]
和ScanOne
中的第一个环境变量(Showem
)。当我与环境变量的数量(44)进行比较时,它会在没有段错误的情况下将它们打印得很好,相比之下45只会给我一个段错误。
我尝试使用指针进行比较为零(搜索空指针):cmp dword [ebp+16+ebx*4],0h
但只返回段错误。我确信空指针位于堆栈中的最后一个环境变量之后,但它就像它不会做任何事情一样。
我哪里错了?
答案 0 :(得分:0)
想继续道歉,这总是发生在我身上(在询问stackoverflow问题后自己解决)。我想当我尝试将指针与0h进行比较时,我输错了一些东西。这就是我的所作所为:
inc ebx
cmp dword [ebp+16+ebx*4],0h
jnz ScanOne
和
inc esi
cmp dword [ebp+16+esi*4],0h
jnz Showem
这很有用。
答案 1 :(得分:0)
如果你的程序有2个,3个或0个args,你的代码仍然有效吗?每个部分由一个NULL指针分隔(4个字节为0)您可以获取参数计数并将其用作数组索引并跳过args直到找到NULL字节。现在你有了你的环境阻止:
extern printf, exit
section .data
fmtstr db "%s", 10, 0
fmtint db "%d", 10, 0
global main
section .text
main:
push ebp
mov ebp, esp
mov ebx, [ebp + 4]
.SkipArgs:
mov edi, dword [ebp + 4 * ebx]
inc ebx
test edi, edi
jnz .SkipArgs
.ShowEnvBlock:
mov edi, dword [ebp + 4 * ebx]
test edi, edi
jz .NoMore
push edi
push fmtstr
call printf
add esp, 4 * 2
inc ebx
jmp .ShowEnvBlock
.NoMore:
push 0
call exit
是的,我在这里使用printf
,但您只需将其与系统调用交换。