Assembly C开关语句的程序集-它是如何工作的?

Assembly C开关语句的程序集-它是如何工作的?,assembly,switch-statement,Assembly,Switch Statement,我正在读一本关于汇编开关语句的书,当输入n为case:100102103104106时,代码有cases/分支。它通过从n中减去100来简化跳转表,然后如果结果大于6,则转到L2中的默认情况,否则将转到与%eax中的值匹配的相应分支 我的问题是: 如果是这样,如果跳转表的索引保存在%eax中,那么第7行不是假定为jmp*.L7(,%eax) 为什么他们在第5行通过执行ja.L2将数字改为无符号 int x位于%ebp+8,int n位于%ebp+12 movl 8(%ebp), %edx

我正在读一本关于汇编开关语句的书,当输入n为case:100102103104106时,代码有cases/分支。它通过从n中减去100来简化跳转表,然后如果结果大于6,则转到L2中的默认情况,否则将转到与%eax中的值匹配的相应分支

我的问题是:

  • 如果是这样,如果跳转表的索引保存在
    %eax
    中,那么第7行不是假定为
    jmp*.L7(,%eax)

  • 为什么他们在第5行通过执行
    ja.L2
    将数字改为无符号

  • int x
    位于
    %ebp+8
    int n
    位于
    %ebp+12

     movl 8(%ebp), %edx 
     movl 12(%ebp), %eax 
     subl $100, %eax 
     cmpl $6, %eax 
     ja .L2 
     jmp *.L7(,%eax,4) 
    .L2: 
     movl $0, %eax 
     jmp .L8 
    .L5: 
     movl %edx, %eax 
    jmp .L9 
     .L3: 
     leal (%edx,%edx,2), %eax 
     leal (%edx,%eax,4), %eax 
     jmp .L8 
    .L4: 
     leal 10(%edx), %eax 
    .L9: 
     addl $11, %eax 
     jmp .L8 
    .L6: 
     movl %edx, %eax 
     imull %edx, %eax 
    .L8: 
    
    跳转表:

    .section .rodata
    .align 4 Align       
    .L7:
    .long .L3         //Case 100: loc_A
    .long .L2         //Case 101: loc_def
    .long .L4         //Case 102: loc_B
    .long .L5        //Case 103: loc_C
    .long .L6        //Case 104: loc_D
    .long .L2       //Case 105: loc_def
    .long .L6        //Case 106: loc_D
    
    如果跳转表的索引保存在
    %eax
    中,那么第7行不是假定为
    jmp*.L7(,%eax)

    跳转表中的每个条目都是一个
    ,即4个字节。因此,
    eax
    按4缩放

    为什么他们在第5行通过执行
    ja.L2
    将数字改为无符号

    关键是要排除任何小于100且大于106的数字。我认为很明显,它是如何排除大于106的值的

    假设
    n
    小于100,例如99。如果我们从中减去100,我们得到-1,当被视为无符号32位值时,它是4294967295,这显然是“高于”6,并且跳转到
    .L2
    ,就像它应该的那样

    subl $100, %eax   ; eax = 99-100 == -1
    cmpl $6, %eax     ; set flags based on -1 - 6 == -7 => ZF=0 and CF=0
    ja .L2            ; jump if ZF=0 and CF=0
    

    这是因为当我们将有符号整数更改为无符号整数时,无符号整数的值将更改为某个较大的数字,因为有符号整数使用2的补码,而无符号整数不使用2的补码?嗯,没有任何实际的符号“更改”。根据特定标志的状态进行条件跳转。在
    ja
    的情况下,如果ZF=0且CF=0,将进行跳转。更新标志的最后一个操作是
    cmp
    ,这实际上是一个减法。减法运算得到ZF=0意味着操作数不相等,要得到CF=0,第一个操作数(
    eax
    )需要无符号大于或等于第二个操作数(
    6
    )。因此,我建议将
    eax
    的值视为未签名,以便更容易对将发生的情况进行推理。