Author Topic: Switch in C and MASM  (Read 796 times)

jj2007

  • Member
  • *****
  • Posts: 13306
  • Assembly is fun ;-)
    • MasmBasic
Switch in C and MASM
« on: January 16, 2022, 09:50:44 PM »
Code: [Select]
#include <stdio.h>
int main(int argc, char* argv[]) {
  int n, svar;
  printf("Please enter an integer: ");
  while (scanf("%d",&svar)!=123) {
//asm ("int $3"); // see switch under the hood
if (svar==12) asm ("int $3");
switch (svar)
{
case 12:
printf("That was case 12\n");
case 24:
printf("That was case 24\n");
case 16:
printf("That was case 16\n");
break;
case 14:
printf("That was case 14\n");
default:
printf("That was default\n");
}
  }
}

Compiled with GCC:
Code: [Select]
0040267F  |.  8B4424 1C     |mov eax, [local.2]                      ; svar
00402683  |>  83F8 0E       |cmp eax, 0E
00402686  |.  74 3B         |je short 004026C3
00402688  |.  7E 26         |jle short 004026B0
0040268A  |.  83F8 10       |cmp eax, 10
0040268D  |.  74 11         |je short 004026A0
0040268F  |.  83F8 18       |cmp eax, 18
00402692  |.  75 3B         |jne short 004026CF
00402694  |>  C70424 724040 |mov dword ptr [local.9], offset 0040407 ; /string => "That was case 24"
0040269B  |.  E8 D4FEFFFF   |call <jmp.&msvcrt.puts>                 ; \MSVCRT.puts
004026A0  |>  C70424 834040 |mov dword ptr [local.9], offset 0040408 ; /string => "That was case 16"
004026A7  |.  E8 C8FEFFFF   |call <jmp.&msvcrt.puts>                 ; \MSVCRT.puts
004026AC  |.^ EB B2         |jmp short 00402660
004026AE  |   66:90         |nop
004026B0  |>  83F8 0C       |cmp eax, 0C
004026B3  |.  75 1A         |jne short 004026CF
004026B5  |.  C70424 614040 |mov dword ptr [local.9], offset 0040406 ; /string => "That was case 12"
004026BC  |.  E8 B3FEFFFF   |call <jmp.&msvcrt.puts>                 ; \MSVCRT.puts
004026C1  |.^ EB D1         |jmp short 00402694
004026C3  |>  C70424 944040 |mov dword ptr [local.9], offset 0040409 ; /string => "That was case 14"
004026CA  |.  E8 A5FEFFFF   |call <jmp.&msvcrt.puts>                 ; \MSVCRT.puts
004026CF  |>  C70424 A54040 |mov dword ptr [local.9], offset 004040A ; /string => "That was default"
004026D6  |.  E8 99FEFFFF   |call <jmp.&msvcrt.puts>                 ; \MSVCRT.puts
004026DB  |.^ EB 83         \jmp short 00402660
004026DD  |   8D76 00       lea esi, [esi]
004026E0  |>  31C0          xor eax, eax

Now the same in Masm32 SDK code:
Code: [Select]
include \masm32\include\masm32rt.inc
.code
start:
  printf("Please enter an integer (123 to exit): ")
  .While 1
switch val(input())
case 123
.break
case 12, 24, 16
printf("That was case 12, 24 or 16\n")
case 14
printf("That was case 14\n")
default
printf("That was default\n")
endsw
  .Endw
  exit
end start

Under the hood:
Code: [Select]
0040100E   > /CC            int3
0040100F   . |68 04010000   push 104                                 ; /Arg2 = 104
00401014   . |68 60214000   push offset 00402160                     ; |Arg1 = Switch.402160
00401019   . |E8 66000000   call 00401084                            ; \Switch.00401084
0040101E   . |68 60214000   push offset 00402160                     ; /s
00401023   . |FF15 E4204000 call near [<&msvcrt.atoi>]               ; \MSVCRT.atoi
00401029   . |83C4 04       add esp, 4
0040102C   . |8BC0          mov eax, eax
0040102E   . |83F8 7B       cmp eax, 7B
00401031   . |75 04         jne short 00401037
00401033   . |EB 46         jmp short 0040107B
00401035   . |EB 42         jmp short 00401079
00401037   > |83F8 10       cmp eax, 10
0040103A   . |74 0A         je short 00401046
0040103C   . |83F8 18       cmp eax, 18
0040103F   . |74 05         je short 00401046
00401041   . |83F8 0C       cmp eax, 0C
00401044   . |75 10         jne short 00401056
00401046   > |68 28204000   push offset 00402028                     ; /format = "That was case 12, 24 or 16"
0040104B   . |FF15 E0204000 call near [<&msvcrt.printf>]             ; \MSVCRT.printf
00401051   . |83C4 04       add esp, 4
00401054   . |EB 23         jmp short 00401079
00401056   > |83F8 0E       cmp eax, 0E
00401059   . |75 10         jne short 0040106B
0040105B   . |68 48204000   push offset 00402048                     ; /format = "That was case 14"
00401060   . |FF15 E0204000 call near [<&msvcrt.printf>]             ; \MSVCRT.printf
00401066   . |83C4 04       add esp, 4
00401069   . |EB 0E         jmp short 00401079
0040106B   > |68 5C204000   push offset 0040205C                     ; /format = "That was default"
00401070   . |FF15 E0204000 call near [<&msvcrt.printf>]             ; \MSVCRT.printf
00401076   . |83C4 04       add esp, 4
00401079   >^\EB 93         jmp short 0040100E

MasmBasic:
Code: [Select]
include \masm32\MasmBasic\MasmBasic.inc
  Init
  PrintLine "Please enter an integer (123 to exit):"
  .While 1
Switch_ Val(Input$("Please enter an integer: "))
Case_ 123
.break
Case_ 12, 24, 16
printf("That was case 12, 24 or 16\n")
Case_ 14
printf("That was case 14\n")
Default_
printf("That was default\n")
Endsw_
  .Endw
EndOfCode

Code: [Select]
004010F9   .  CC            int3
004010FA   .  EB 30         jmp short 0040112C
004010FC   >  EB 53         jmp short 00401151                       ; break
004010FE   .  C3            retn
004010FF   >  68 7A704000   push offset 0040707A                     ; /format = "That was case 12, 24 or 16"
00401104   .  FF15 84794000 call near [<&msvcrt.printf>]             ; \MSVCRT.printf
0040110A   .  83C4 04       add esp, 4
0040110D   .  C3            retn                                     ; Jump to 40114C
0040110E   >  68 98704000   push offset 00407098                     ; /format = "That was case 14"
00401113   .  FF15 84794000 call near [<&msvcrt.printf>]             ; \MSVCRT.printf
00401119   .  83C4 04       add esp, 4
0040111C   .  C3            retn                                     ; Jump to 40114C
0040111D   >  68 AC704000   push offset 004070AC                     ; /format = "That was default"
00401122   .  FF15 84794000 call near [<&msvcrt.printf>]             ; \MSVCRT.printf
00401128   .  83C4 04       add esp, 4
0040112B   .  C3            retn                                     ; Jump to 40114C
0040112C   >  68 4C114000   push 0040114C
00401131   .  83F8 7B       cmp eax, 7B
00401134   .^ 74 C6         je short 004010FC                        ; break
00401136   .  83F8 0C       cmp eax, 0C
00401139   .^ 74 C4         je short 004010FF                        ; case 12
0040113B   .  83F8 18       cmp eax, 18
0040113E   .^ 74 BF         je short 004010FF                        ; case 24
00401140   .  83F8 10       cmp eax, 10
00401143   .^ 74 BA         je short 004010FF                        ; case 16
00401145   .  83F8 0E       cmp eax, 0E
00401148   .^ 74 C4         je short 0040110E                        ; case 14
0040114A   .^ EB D1         jmp short 0040111D                       ; case default

LiaoMi

  • Member
  • *****
  • Posts: 1038
Re: Switch in C and MASM
« Reply #1 on: January 17, 2022, 05:22:50 AM »
Clang 13.0 :tongue:

Code: [Select]
main:                                   # @main
        push    rbp
        mov     rbp, rsp
        sub     rsp, 32
        mov     dword ptr [rbp - 4], 0
        mov     dword ptr [rbp - 8], edi
        mov     qword ptr [rbp - 16], rsi
        movabs  rdi, offset .L.str
        mov     al, 0
        call    printf
.LBB0_1:                                # =>This Inner Loop Header: Depth=1
        movabs  rdi, offset .L.str.1
        lea     rsi, [rbp - 24]
        mov     al, 0
        call    __isoc99_scanf
        cmp     eax, 123
        je      .LBB0_11
        cmp     dword ptr [rbp - 24], 12
        jne     .LBB0_4
        int3
.LBB0_4:                                #   in Loop: Header=BB0_1 Depth=1
        mov     eax, dword ptr [rbp - 24]
        add     eax, -12
        mov     ecx, eax
        mov     qword ptr [rbp - 32], rcx       # 8-byte Spill
        sub     eax, 12
        ja      .LBB0_9
        mov     rax, qword ptr [rbp - 32]       # 8-byte Reload
        mov     rax, qword ptr [8*rax + .LJTI0_0]
        jmp     rax
.LBB0_5:                                #   in Loop: Header=BB0_1 Depth=1
        movabs  rdi, offset .L.str.2
        mov     al, 0
        call    printf
.LBB0_6:                                #   in Loop: Header=BB0_1 Depth=1
        movabs  rdi, offset .L.str.3
        mov     al, 0
        call    printf
.LBB0_7:                                #   in Loop: Header=BB0_1 Depth=1
        movabs  rdi, offset .L.str.4
        mov     al, 0
        call    printf
        jmp     .LBB0_10
.LBB0_8:                                #   in Loop: Header=BB0_1 Depth=1
        movabs  rdi, offset .L.str.5
        mov     al, 0
        call    printf
.LBB0_9:                                #   in Loop: Header=BB0_1 Depth=1
        movabs  rdi, offset .L.str.6
        mov     al, 0
        call    printf
.LBB0_10:                               #   in Loop: Header=BB0_1 Depth=1
        jmp     .LBB0_1
.LBB0_11:
        mov     eax, dword ptr [rbp - 4]
        add     rsp, 32
        pop     rbp
        ret
.LJTI0_0:
        .quad   .LBB0_5
        .quad   .LBB0_9
        .quad   .LBB0_8
        .quad   .LBB0_9
        .quad   .LBB0_7
        .quad   .LBB0_9
        .quad   .LBB0_9
        .quad   .LBB0_9
        .quad   .LBB0_9
        .quad   .LBB0_9
        .quad   .LBB0_9
        .quad   .LBB0_9
        .quad   .LBB0_6
.L.str:
        .asciz  "Please enter an integer: "

.L.str.1:
        .asciz  "%d"

.L.str.2:
        .asciz  "That was case 12\n"

.L.str.3:
        .asciz  "That was case 24\n"

.L.str.4:
        .asciz  "That was case 16\n"

.L.str.5:
        .asciz  "That was case 14\n"

.L.str.6:
        .asciz  "That was default\n"

LiaoMi

  • Member
  • *****
  • Posts: 1038
Re: Switch in C and MASM
« Reply #2 on: January 17, 2022, 05:27:53 AM »
Intel C++ Compiler 2021.5

Code: [Select]
.L_2__STRING.0:
        .long   1634036816
        .long   1696621939
        .long   1919251566
        .long   544104736
        .long   1702129257
        .long   980575591
        .word   32
.L_2__STRING.6:
        .word   25637
        .byte   0
.L_2__STRING.1:
        .long   1952540756
        .long   1935767328
        .long   1935762208
        .long   842080357
        .word   10
.L_2__STRING.2:
        .long   1952540756
        .long   1935767328
        .long   1935762208
        .long   875700325
        .word   10
.L_2__STRING.3:
        .long   1952540756
        .long   1935767328
        .long   1935762208
        .long   909189221
        .word   10
.L_2__STRING.4:
        .long   1952540756
        .long   1935767328
        .long   1935762208
        .long   875634789
        .word   10
.L_2__STRING.5:
        .long   1952540756
        .long   1935767328
        .long   1717920800
        .long   1953264993
        .word   10

main:
        push      rbp                                           #2.34
        mov       rbp, rsp                                      #2.34
        sub       rsp, 64                                       #2.34
        mov       DWORD PTR [-24+rbp], edi                      #2.34
        mov       QWORD PTR [-16+rbp], rsi                      #2.34
        mov       eax, offset flat: .L_2__STRING.0              #4.3
        mov       rdi, rax                                      #4.3
        mov       eax, 0                                        #4.3
        call      printf                                        #4.3
        mov       DWORD PTR [-64+rbp], eax                      #4.3
..B1.2:                         # Preds ..B1.22 ..B1.24 ..B1.18
        mov       eax, offset flat: .L_2__STRING.6              #5.10
        lea       rdx, QWORD PTR [-60+rbp]                      #5.10
        mov       rdi, rax                                      #5.10
        mov       rsi, rdx                                      #5.10
        mov       eax, 0                                        #5.10
        call      __isoc99_scanf                                #5.10
        mov       DWORD PTR [-56+rbp], eax                      #5.10
        mov       eax, DWORD PTR [-56+rbp]                      #5.10
        cmp       eax, 123                                      #5.29
        je        ..B1.15       # Prob 50%                      #5.29
        mov       eax, DWORD PTR [-60+rbp]                      #7.6
        cmp       eax, 12                                       #7.12
        jne       ..B1.6        # Prob 50%                      #7.12
        int $3
..B1.6:                         # Preds ..B1.5 ..B1.4
        mov       eax, DWORD PTR [-60+rbp]                      #8.10
        mov       DWORD PTR [-52+rbp], eax                      #8.10
        mov       eax, DWORD PTR [-52+rbp]                      #8.10
        cmp       eax, 12                                       #8.10
        je        ..B1.10       # Prob 50%                      #8.10
        mov       eax, DWORD PTR [-52+rbp]                      #8.10
        cmp       eax, 24                                       #8.10
        je        ..B1.11       # Prob 50%                      #8.10
        mov       eax, DWORD PTR [-52+rbp]                      #8.10
        cmp       eax, 16                                       #8.10
        je        ..B1.12       # Prob 50%                      #8.10
        mov       eax, DWORD PTR [-52+rbp]                      #8.10
        cmp       eax, 14                                       #8.10
        je        ..B1.13       # Prob 50%                      #8.10
        jmp       ..B1.14       # Prob 100%                     #8.10
..B1.10:                        # Preds ..B1.6
        mov       eax, offset flat: .L_2__STRING.1              #11.2
        mov       rdi, rax                                      #11.2
        mov       eax, 0                                        #11.2
        call      printf                                        #11.2
        mov       DWORD PTR [-48+rbp], eax                      #11.2
..B1.11:                        # Preds ..B1.20 ..B1.7
        mov       eax, offset flat: .L_2__STRING.2              #13.2
        mov       rdi, rax                                      #13.2
        mov       eax, 0                                        #13.2
        call      printf                                        #13.2
        mov       DWORD PTR [-44+rbp], eax                      #13.2
..B1.12:                        # Preds ..B1.21 ..B1.8
        mov       eax, offset flat: .L_2__STRING.3              #15.2
        mov       rdi, rax                                      #15.2
        mov       eax, 0                                        #15.2
        call      printf                                        #15.2
        mov       DWORD PTR [-40+rbp], eax                      #15.2
        jmp       ..B1.2        # Prob 100%                     #15.2
..B1.13:                        # Preds ..B1.9
        mov       eax, offset flat: .L_2__STRING.4              #18.2
        mov       rdi, rax                                      #18.2
        mov       eax, 0                                        #18.2
        call      printf                                        #18.2
        mov       DWORD PTR [-36+rbp], eax                      #18.2
..B1.14:                        # Preds ..B1.23 ..B1.9
        mov       eax, offset flat: .L_2__STRING.5              #20.2
        mov       rdi, rax                                      #20.2
        mov       eax, 0                                        #20.2
        call      printf                                        #20.2
        mov       DWORD PTR [-32+rbp], eax                      #20.2
        jmp       ..B1.2        # Prob 100%                     #20.2
..B1.15:                        # Preds ..B1.3
        mov       eax, 0                                        #23.1
        leave                                                   #23.1
        ret                                                     #23.1

NoCforMe

  • Member
  • ****
  • Posts: 866
Re: Switch in C and MASM
« Reply #3 on: January 17, 2022, 03:00:43 PM »
Kind of a tangent here, and not exactly on topic, but I'm curious: here's some of your "under the hood" code:

0040100E   > /CC            int3
0040100F   . |68 04010000   push 104                                 ; /Arg2 = 104
00401014   . |68 60214000   push offset 00402160                     ; |Arg1 = Switch.402160
00401019   . |E8 66000000   call 00401084                            ; \Switch.00401084
0040101E   . |68 60214000   push offset 00402160                     ; /s
00401023   . |FF15 E4204000 call near [<&msvcrt.atoi>]               ; \MSVCRT.atoi
00401029   . |83C4 04       add esp, 4
0040102C   . |8BC0          mov eax, eax
0040102E   . |83F8 7B       cmp eax, 7B
00401031   . |75 04         jne short 00401037
00401033   . |EB 46         jmp short 0040107B
00401035   . |EB 42         jmp short 00401079
00401037   > |83F8 10       cmp eax, 10
0040103A   . |74 0A         je short 00401046
0040103C   . |83F8 18       cmp eax, 18
0040103F   . |74 05         je short 00401046
00401041   . |83F8 0C       cmp eax, 0C
00401044   . |75 10         jne short 00401056

[...]

So the two lines I turned red: the first one does nothing. Doesn't set processor flags or anything else. Might as well have coded a NOP here.
Second one is an island that's never reached from any other part of the code.
Why would a compiler do such stupid things?

(I tried to format this as "code" but then you can't use the "color=" tag ... waaaah)

jj2007

  • Member
  • *****
  • Posts: 13306
  • Assembly is fun ;-)
    • MasmBasic
Re: Switch in C and MASM
« Reply #4 on: January 17, 2022, 08:37:28 PM »
You are right, in fact I noticed that, too. It's a little flaw in the Masm32 and MasmBasic macros.