-1

I have the following code. And I want to complete the assembly code as indicated below:

int main(void)
{
    int x = 10;

    int i=0;
    label1:


    asm (.....) // code to add here: if i>=x then jump to label2

    printf("%d\n",i);

    i++;
    asm (.....) // code to add here: jump to label 1
    label2:

    printf("out\n");
}

My machine is x86 and the Operating system is Ubuntu 12

MOHAMED
  • 41,599
  • 58
  • 163
  • 268
  • 3
    What would this achieve? Isn't the C comparison going to be the same?! – Anirudh Ramanathan Jan 25 '13 at 14:06
  • So, what have you tried? Which instruction(s) do you think you need to use to do this? – unwind Jan 25 '13 at 14:06
  • I know that I have use some thing like JNE but I m not able to resolve this problem. I made some research in bing and in stackoverflow but without any result – MOHAMED Jan 25 '13 at 14:08
  • @Cthulhu I have my reason to use assembly code and I could not communicate it – MOHAMED Jan 25 '13 at 14:12
  • 2
    @MohamedKALLEL Would you mind telling us why you can't talk about the reasons why to do it with inline assembly? What you do is building a while loop 'by hand'. So what's the secret? – junix Jan 25 '13 at 14:15
  • @MohamedKALLEL - Step 1 should always be to search for the op codes for your architecture, read them and read examples. Just a search for `x86 assembly greater than` in Google gives some great examples of what you want. By the third or forth hit you'll find sites like [this one](http://www.cs.virginia.edu/~evans/cs216/guides/x86.html) which gives a great guide to the instructions, the registers, and examples. – Mike Jan 25 '13 at 15:12

3 Answers3

5

First, get yourself a list of x86 op codes, should be easy to find online.

The asm() function follows this order:

asm ( "assembly code"
           : output operands                  /* optional */
           : input operands                   /* optional */
           : list of clobbered registers      /* optional */
);

Second, one major problem you have is you can't "jump" to a C label, you need to make your label an "assembly" label to be able to jump to it. ex:

int main()
{
  asm("jmp .end");    // make a call to jmp there
  printf("Hello ");
  asm(".end:");       //make a "jumpable" label
  printf("World\n");
  return 0;
}

Output of this program is simply "World" as we jumped over the "Hello ". Here's the same example but with a comparative jump:

int main()
{
    int x = 5, i = 0;
    asm(".start:");
    asm("cmp %0, %1;"   // compare input 1 to 2
        "jge .end;"     // if i >= x, jump to .end
        :               // no output from this code
        : "r" (x), "r" (i));  // input's are var x and i
    printf("Hello ");
    i++;
    asm("jmp .start;");    
    asm(".end:");
    printf("World\n");
    return 0;
}
MOHAMED
  • 41,599
  • 58
  • 163
  • 268
Mike
  • 47,263
  • 29
  • 113
  • 177
  • +1 Nice generic answer working around the 'unknowns' of the question! – Veger Jan 25 '13 at 14:35
  • just 2 remarks (Remark1) I tested your code and I had to modify `asm("cmp %1, %2;" ` by `asm("cmp %0, %1;" ` inorder to get the code compile so please update it – MOHAMED Jan 25 '13 at 15:20
  • @MohamedKALLEL - Good catch. ;) copy and paste error from some other code where I was saving a result. Your outputs will start at the lower numbers (`%0`) in that case. Since there are no outputs in this example all the inputs should have "shifted down". I updated that. – Mike Jan 25 '13 at 15:23
  • Thank you for the update, (Remark2) could you please update you code to be adequate with the question code there is a loop in my question – MOHAMED Jan 25 '13 at 15:38
  • I updated myself thanks again for the answer – MOHAMED Jan 25 '13 at 15:56
  • **You can't *safely* `jmp` between asm statements**. If execution enters the top of an asm statement, the compiler expects it to come out the bottom of the *same* asm statement, not some other one (unless you [use `asm goto`](https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#GotoLabels) to maybe jump to a *C* label). Expect this to break with optimization enabled. (The only case where you can jump to another asm statement is if you jump *back* without leaving asm and having any C run, e.g. define a helper function somewhere that your asm statement uses.) – Peter Cordes Dec 18 '20 at 05:48
2

If you are not really bound to use assembly here, you can use C more easily and at least as efficient as the assembly version would be:

int x = 10;
int i = 0;
while(i < x) {
  printf("%d\n",i);
  i++;
}
printf("out\n");

(a for-loop is also suitable)

Veger
  • 37,240
  • 11
  • 105
  • 116
  • I know the while loop. I have my reasons to use assembly – MOHAMED Jan 25 '13 at 14:11
  • Maybe you need to update your question elaborating on these reasons. Otherwise people will tell you that using a `while`-loop is much easier (as I did...) – Veger Jan 25 '13 at 14:19
  • +1 `you can use C more easily and at least as efficient as the assembly version` - absolutely correct, and frankly given the shroud of mystery.. the better answer. – Mike Jan 25 '13 at 15:08
0

I don't remember the semantics to using assembler within c, but normally when you compare a number in assembler, you subtract the numbers from one another. If they were the same number, the zero bit will be set, so you can do a conditional jump. Be sure to use the correct registers to match the size of int.

Very rough example code (this is off the top of my head, and it has been years since I wrote assembler):

#load value to compare against into BX
#load number to check into AX
CMP AX, BX
JE label

updated: changed SUB to CMP as suggested by @harold

pgreen2
  • 3,601
  • 3
  • 32
  • 59
  • Or, you know, `cmp`.. the result of the subtraction isn't needed, only the flags. And `jge`, because he wasn't comparing for equality but for "signed greater or equal". – harold Jan 25 '13 at 14:31
  • You are correct. It has been a while; I've updated my response. – pgreen2 Jan 25 '13 at 14:35