Linux 具有任意值的cmp等于0

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

我试图在汇编中创建一个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  '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、1、2和3进行比较
  • 如果与1、2或3的比较成功,请跳转到相应的标签
  • 否则,跳转或跳转到
    案例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位操作数大小的助记符的约定尤其不一致和冲突。