您正在将指针与 arg 字符串的 8 个字节进行比较。
要比较字符串,由于您使用的是 C 运行时,您可以像在 C: 中那样使用strcmp 进行比较。
.global main
.text
strIArg: .asciz "-i"
strHello: .asciz "Hello.
"
main:
sub $8, %rsp
#At least two args?
cmp $2, %edi
jb 1f
#2nd arg is equal to strIArg?
mov 8(%rsi), %rdi #argv[1] in RDI
lea strIArg(%rip), %rsi #"-i" in RSI (I'm making a PIE, hence the RIP-relative addressing)
call strcmp
test %eax, %eax #strcmp returns 0 if the two strings are equal
jnz 1f
#OK, arg found
lea strHello(%rip), %rdi
call printf
1:
xor %edi, %edi
call exit
或者,如果您的参数足够短并且您的程序非常简单,您可以减少对strcmp 的调用以提高性能。
.global main
.text
strHello: .asciz "Hello.
"
main:
sub $8, %rsp
#At least two args?
cmp $2, %edi
jb 1f
#2nd arg is equal to strIArg?
mov 8(%rsi), %rdi
cmpb $0, (%rdi)
je 1f #Empty string?
cmpw $0x692d, (%rdi) #Starts with -i ?
jne 1f
cmpb $0, 2(%rdi) #And then it ends?
jne 1f
#OK, arg found
lea strHello(%rip), %rdi
call printf
1:
xor %edi, %edi
call exit
但我不会推荐它,除非是在最简单的情况下,因为 GAS doesn't support string literals as immediates 并且您需要自己转换字符串(注意 x86 的小端序),这会降低代码的可读性。
最后,对于在 POSIX 系统上运行的更复杂的程序,您可能需要考虑getopt_long and variants。
下面是一个程序示例,它欢迎在命令行上传递的名称,并采用两个可选参数来修改其行为。
请注意getopt_long 将如何处理参数的重新排序、处理极端情况(例如,当用户将-un X 作为-u -n X 的缩写传递时)以及为我们处理--。
.global main
.data
#Name to use for the greetings
name: .quad defaultName
#Greeting string to use
greetings: .quad strHello
#The long options accepted
nameOpt:
.quad nameOptName #name
.quad 1 #has arg
.quad 0 #ptr to flag to update with val (0 to make getopt_long return val instead)
.quad 'n' #val
uppercaseOpt:
.quad uppercaseOptName
.quad 0
.quad 0
.quad 'u'
nullOpt:
.quad 0
.quad 0
.quad 0
.quad 0 #Last option must be null
.text
#Greetings strings
strHello: .asciz "Hello %s from %s!
"
strHelloUpper: .asciz "HELLO %s FROM %s!
"
#Default name
defaultName: .asciz "Margaret"
nameOptName: .asciz "name"
uppercaseOptName: .asciz "upper"
#The short options accepted, note how we use "n" and "u" for both the long and short options
#this is to reuse the logic but getopt_long allows to distinguish the two cases
shortOpts: .asciz "n:u"
main:
sub $8, %rsp
#If you return from main, push r12 and r13 (and then pop them)
#Move the args to non-volatile registers
mov %rdi, %r12 #R12 = argc
mov %rsi, %r13 #R13 = argv
parseArgs:
mov %r12, %rdi
mov %r13, %rsi
lea shortOpts(%rip), %rdx
lea nameOpt(%rip), %rcx
xor %r8, %r8
call getopt_long
#Found --name/-n?
cmp $'n', %al
je foundName
#Found --upper/-u?
cmp $'u', %al
je foundUpper
#Everything else is an error or end of option args (-1)
test %eax, %eax
jns parseError
#Args are parsed, optind is the index of the first non optional arg
lea (%r13, %r12, 8), %r12 #R12 = one past the last argument
mov optind(%rip), %ecx #RCX = current index
lea (%r13, %rcx, 8), %r13 #R13 = pointer to pointer to current argument
#Print the greetings
doGreetings:
#Stop?
cmp %r12, %r13
jae end
#Print the current greetings
mov greetings(%rip), %rdi
mov (%r13), %rsi
mov name(%rip), %rdx
call printf
#Next arg
add $8, %r13
jmp doGreetings
end:
xor %edi, %edi
call exit
foundName:
#Here optarg is a pointer to the argument value
#Copy the pointer to name
mov optarg(%rip), %rdx
mov %rdx, name(%rip)
jmp parseArgs
foundUpper:
#This option has no argument, we just set the greetings to strHelloUpper
lea strHelloUpper(%rip), %rcx
mov %rcx, greetings(%rip)
jmp parseArgs
parseError:
#Just return 1
mov $1, %edi
call exit
你可以用 GCC 编译这个程序,然后运行它:
./greet Alice Bob Eve
./geeet Alice --name Bob
./greet Alice --upper
./greet --name Eve --upper Alice
./greet -u Alice
./greet Alice -un Bob