Linux 具有任意值的cmp等于0
我试图在汇编中创建一个switch语句;然而,我似乎总是被第一种情况所困扰,不管它的价值是什么:Linux 具有任意值的cmp等于0,linux,assembly,nasm,Linux,Assembly,Nasm,我试图在汇编中创建一个switch语句;然而,我似乎总是被第一种情况所困扰,不管它的价值是什么: SECTION .data newLine db 0xA,0xD NewLen equ $- newLine nvalue dw 2 ; nth number for case msg0 db 'a', 0xa msg1 db 'b', 0xa msg2 db
SECTION .data
newLine db 0xA,0xD
NewLen equ $- newLine
nvalue dw 2 ; nth number for case
msg0 db 'a', 0xa
msg1 db 'b', 0xa
msg2 db 'c', 0xa
msg3 db 'd', 0xa
defaultMsg db 'e'
SECTION .text
global _start
_start:
mov eax, nvalue
cmp eax, 0
je case0
cmp eax, 1
je case1
cmp eax, 2
je case2
cmp eax, 3
je case3
case0:
mov edx, 2
mov eax, 4
mov ebx, 1
mov ecx, msg0
mov edx, 1
int 80h
call printNL
call quit
case1:
mov edx, 2
mov eax, 4
mov ebx, 1
mov ecx, msg1
mov edx, 1
int 80h
call printNL
call quit
case2:
mov edx, 2
mov eax, 4
mov ebx, 1
mov ecx, msg2
mov edx, 1
int 80h
call printNL
call quit
case3:
mov edx, 2
mov eax, 4
mov ebx, 1
mov ecx, msg3
mov edx, 1
int 80h
call printNL
call quit
mov edx, 2
mov eax, 4
mov ebx, 1
mov ecx, defaultMsg
mov edx, 1
int 80h
call printNL
call quit
printNL:
mov edx, NewLen
mov ecx, newLine
mov ebx, 1
mov eax, 4
int 80h
quit:
mov ebx, 0
mov eax, 1
int 80h
ret
字符串输出始终为“a”(当nvalue变量为0时,情况为0)。当nvalue为2时,为什么要这样做
replace:
nvalue dw 2 ; nth number for case
with:
nvalue dd 2 ; nth number for case
dos asm很古怪
此外,您可能需要添加一个默认案例——这就是它失败的原因
mov eax, nvalue
cmp eax, 0
je case0
cmp eax, 1
je case1
cmp eax, 2
je case2
cmp eax, 3
je case3
case0:
这段代码的作用是
nvalue
的地址加载到eax
中案例0
nvalue
的值读入eax
。这是由
mov eax, [nvalue]
如果您使用dd
定义了nvalue
。如果使用dw
将其保持为现在的状态,则加载可能如下
movzx eax, word [nvalue]
第二点,如果您不想在所有比较都失败时失败,您可能需要在case0
标签之前添加一个跳转
或者,将打印defaultMsg的块放在
je case3
之间<代码>案例0:。通过这种方式,您可以删除所需的额外jmp
mov eax,[nvalue]
查看您正在加载的是地址而不是值。此外,您还使用了错误的指令,您需要双字的dd
。或者使用movzx-eax,word[nvalue]
。非常感谢@Jester!这有助于我更好地理解它。呼叫退出
非常令人困惑!最好写jmp quit
。打印defaultMsg的块应该直接位于标签case0:
上方。在汇编编程中,缩进文本对于可读性很重要,但它并没有说明任何逻辑结构,如开关。谢谢。我认为我的默认情况是在“case”函数之外打印“defaultMsg”的代码块。不是这样吗?从DOS的汇编程序来看,这不是DOS,而是Linux。int0x80
“DOS asm”不是“DOS的汇编程序”。它最初是作为一个可移植的汇编程序开发的,可以在非DOS机器上运行良好,以便于在GNU/Linux机器上开发像syslinux和isolinux这样的引导加载程序。它使用那种模棱两可的dos格式,这使它成为dos的汇编程序;更糟糕的是,它重新定义了它,从而进入了第三种语法。OP使用了一个mov符号eax
,dos汇编程序将从内存中加载该符号,nasm将变成dos asm所称的lea
;只有这样才能正确地说“语法错误”。所以,对了,从技术上讲不是dos,但仍然是dos。谢谢@Ruslan。你说的“跳开”是什么意思?你指的是“违约”案例吗?如果是这样,我认为我的默认设置是在所有“case”函数之外打印defaultMsg。@SJCypher您的默认设置是在未执行分支时(ZF==0
)。如果没有执行,您将执行案例0
代码。(主题外:您的答案看起来是正确的;是什么问题导致您决定删除它?您可以回答我对该问题的评论,而不是此评论线程)@PeterCordes我发现说*L
有些奇怪是不对的:首先,yasm和fasm,例如,似乎理解spl
,但不理解spb
。如果我真的删除了这一部分,剩下的将只是讨论便利性变量,这从评论中似乎很明显。在任何情况下,在取消删除之前都需要对答案进行修改。有关r8..r15的l
(AMD)与b
(英特尔)后缀的更多历史,请参阅我在该问题下的评论,并提供链接。原始-8寄存器始终使用l
,以与al
/bl
/。。。但是,是的,它与AT&T语法的l
=长32位操作数大小的助记符的约定尤其不一致和冲突。