0

I would like to know how to implement this lines of code into x86 masm assembly:

    if (x >= 1 && x <= 100) {
        printsomething1();
    } else if (x >= 101 && x <= 200) {
        printsomething2();
    } else {
        printsomething3();
    }

2 Answers2

3

I'd break it into contiguous ranges, (assuming x is unsigned) like:

  • x is 0, do printsomething3()
  • x is 1 to 100, do nothing printsomething1()
  • x is 101 to 200, do nothing printsomething2()
  • x is 201 or higher, do nothing printsomething3()

Then work from lowest to highest, like:

    ;eax = x;

    cmp eax,0
    je .printsomething3
    cmp eax,100
    jbe .printsomething1
    cmp eax,200
    jbe .printsomething2
    jmp .printsomething3

If the only difference is the string they print (and not the code they use to print it) I'd go one step further:

    mov esi,something3     ;esi = address of string if x is 0
    cmp eax,0
    je .print
    mov esi,something1     ;esi = address of string if x is 1 to 100
    cmp eax,100
    jbe .print
    mov esi,something2     ;esi = address of string if x is 101 to 200
    cmp eax,200
    jbe .print
    mov esi,something3     ;esi = address of string if x is 201 or higher
    jmp .print
Brendan
  • 35,656
  • 2
  • 39
  • 66
  • upvoted, but you're assuming that `x` is unsigned. I guess that's equivalent in this case, because any negative will be a large unsigned number above 200. If you start with `sub eax, 1`, then you can use unsigned-compare for the ranges (`cmp eax,99` and `cmp eax,199`) and avoid one `jcc`, though. eax=0 will wrap to a large unsigned value. – Peter Cordes Oct 29 '18 at 06:39
0

If you have access to a decent C compiler, you can compile it into assembly language. For gcc use the -S flag:

gcc test.c -S

This creates the file test.s which contains the assembly language output which can be assembled and linked if needed.

For example, to make your code compile successfully, I rewrote it slightly to this:

#include <stdio.h>
#include <stdlib.h>

void printsomething (int y)
{
    printf ("something %d", y);
}

void func (int x)
{
    if (x >= 1 && x <= 100)
        printsomething(1);
    else
    if (x >= 101  && x <= 200)
        printsomething(2);
    else
        printsomething(3);
}

int main (int argc, char **argv)
{
    int x = 0;
    if (argc > 1)
        x = atoi (argv [1]);
    return 0;
}

It compiles into this assembler:

    .file   "s.c"
    .text
    .section    .rodata
.LC0:
    .string "something %d"
    .text
    .globl  printsomething
    .type   printsomething, @function
printsomething:
.LFB5:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    subq    $16, %rsp
    movl    %edi, -4(%rbp)
    movl    -4(%rbp), %eax
    movl    %eax, %esi
    movl    $.LC0, %edi
    movl    $0, %eax
    call    printf
    nop
    leave
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE5:
    .size   printsomething, .-printsomething
    .globl  func
    .type   func, @function
func:
.LFB6:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    subq    $16, %rsp
    movl    %edi, -4(%rbp)
    cmpl    $0, -4(%rbp)
    jle .L3
    cmpl    $100, -4(%rbp)
    jg  .L3
    movl    $1, %edi
    call    printsomething
    jmp .L4
.L3:
    cmpl    $100, -4(%rbp)
    jle .L5
    cmpl    $200, -4(%rbp)
    jg  .L5
    movl    $2, %edi
    call    printsomething
    jmp .L4
.L5:
    movl    $3, %edi
    call    printsomething
.L4:
    nop
    leave
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE6:
    .size   func, .-func
    .globl  main
    .type   main, @function
main:
.LFB7:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    subq    $32, %rsp
    movl    %edi, -20(%rbp)
    movq    %rsi, -32(%rbp)
    movl    $0, -4(%rbp)
    cmpl    $1, -20(%rbp)
    jle .L7
    movq    -32(%rbp), %rax
    addq    $8, %rax
    movq    (%rax), %rax
    movq    %rax, %rdi
    call    atoi
    movl    %eax, -4(%rbp)
.L7:
    movl    $0, %eax
    leave
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE7:
    .size   main, .-main
    .ident  "GCC: (GNU) 7.3.1 20180712 (Red Hat 7.3.1-6)"
    .section    .note.GNU-stack,"",@progbits

Examine the func: part of it and you'll see how it sets up the comparisons with 1, 100, 101, etc.

wallyk
  • 56,922
  • 16
  • 83
  • 148
  • Compiling without optimization does not make nice human-readable code, and you didn't even strip out the .cfi directives ([How to remove "noise" from GCC/clang assembly output?](https://stackoverflow.com/q/38552116)). You wrote a function that takes an arg, so it won't optimize away with `-O3`. You should use at least `-O1`. "go ask a compiler" is the right answer, but this is barely more helpful than a comment + a Godbolt link. – Peter Cordes Oct 29 '18 at 06:35
  • @PeterCordes: Considering spirit of the question, providing tools and a path for the OP to tinker and find the answer seemed more appropriate than literally answering the question. – wallyk Oct 29 '18 at 06:53
  • Right, but if you're going to do that, compile with `-O3` and maybe comment the asm. Because `-O0` output is *not* how you should do it. So you *haven't* shown the OP how to help themself in a useful way. – Peter Cordes Oct 29 '18 at 07:15