0

I'm practicing some basic assembly online and I'm very new in this field so I tried writing the equivalent of the following C program:


int a,b,c;

main () {
int d;
  a=28;
  b=a+31;
  c=14;
  if (a>23) {
    c=a%(b&a%10)/c;
  }
  d=c;
}

Here's what I did:


segment .text
global _start
_start:
mov eax, 28 ; a=28
mov ebx, 0  ; b=0
mov ebx, eax; b=28
add ebx, 31; b=28+31
mov ecx, 14; c=14
;
cmp eax, 23 ; a>23
jnle thenblock; there's no else block so we jump straight into thenblock if a>23
;
thenblock:
and eax, ebx ; a=b&a?
mov esi, eax ; save the value of eax because when we perform modulo it will be overwritten
mov edx, 0 ; our remainder will be placed here
mov ebx, 10 ; we divide by 10
div ebx ; divide eax by ebx, where the remainder will be placed in edx;
;
mov eax, esi ; we restore eax
mov ebx, edx ; ebx is (b&a%10), we divide eax by it
mov edx, 0 ; our remainder will be placed here
div ebx
;
mov ebx, edx ; we move a%(b&a%10) to ebx
mov eax, esi ; we restore eax again
div ebx ; divide eax by ebx
;
next:
mov edx, eax
ret

Now, I'm fairly certain that this has multiple errors which I don't know how to fix. I'd be very thankful if someone could point out what mistakes I made and how to fix them.

NOTE: I used a version of a nasm compiler with GoLinker. I compiled using nasm -f win32 sample.asm

Jester
  • 56,577
  • 4
  • 81
  • 125
l0ner9
  • 263
  • 1
  • 7
  • 1
    If you are on windows the only reason for a crash I can see is that you forgot to zero `edx` for the last division. As for other problems, for example `jnle thenblock;` makes little sense as the `thenblock` is immediately after that. You are missing a jump to skip that (you probably want to reverse the condition). – Jester Nov 23 '21 at 14:58
  • 1
    Can you `ret` from your `_start` entry point on Windows? I know on Linux you can't because there is no return address on the stack; you have to invoke an exit system call directly. – Nate Eldredge Nov 23 '21 at 15:02
  • Hi Jester and Thanks! Yes I am on a 64 bit installation of Windows. As for the jnle thenblock, I was confused because I didn't have an '''else''' clause after the '''if''' clause so I wasn't sure how to proceed! – l0ner9 Nov 23 '21 at 15:02
  • @Jester could you point out where exactly is ```mov edx, 0``` neccessary? I tried to null the register before the ```div ebx ; divide eax by ebx``` line but it crashes anyway. – l0ner9 Nov 23 '21 at 15:38
  • 1
    Yeah, there. If it's not that then Nate is right and you can't `ret`on windows either. Try changing that to a `jmp $` and see if it hangs instead of crashing. – Jester Nov 23 '21 at 15:39
  • Regarding zeroing edx, see https://stackoverflow.com/questions/38416593/why-should-edx-be-0-before-using-the-div-instruction/38416896#38416896 – Nate Eldredge Nov 23 '21 at 16:03
  • 1
    Note that high-level control structures like `if`, `while`, etc, don't directly exist in assembly, and it may not be helpful to think in those terms. You have to do everything in terms of conditional jumps, and pay careful attention to what those instructions actually do - depending on the condition, you either take the jump, or don't take it and go on to the next instruction. The C equivalent is `if (cond) goto label;`. – Nate Eldredge Nov 23 '21 at 16:06
  • 2
    In fact, it can be helpful to start by rewriting in a limited version of C. Pretend you have no `for, while, do`. You can use `if`, but the only statement it's allowed to control is a single `goto`, and `else` is not allowed. On the other hand, you may use `goto` freely, and put labels wherever you want. – Nate Eldredge Nov 23 '21 at 16:09
  • @NateEldredge: `do{}while()` also maps directly to a single backwards compare-and-branch in asm. ([Why are loops always compiled into "do...while" style (tail jump)?](https://stackoverflow.com/q/47783926)). When I have a specific idea in mind about how I want some C to compile to efficient asm for before and inside a loop, I often write it in terms of a do{}while loop. Although that's getting a bit off topic for this specific question which doesn't involve any loops, just some dead code that only writes to local vars and returns 0. (Or maybe encounters divide-by-zero UB with different vals) – Peter Cordes Nov 23 '21 at 23:48

0 Answers0