1

I'm doing a program in assembly to read a disk through ports (0x1f0-0x1f7) and I'm mixing it with c. I have a function in assembly that I will call in my c main funtion. My main function as 1 parameter: sectors to read:

Kernel.c

extern int _readd(int nmrsector);
(...)
int sector = 257;
int error = _readd(sector);
if(error == 0) PrintString("Error"); //It is declared on my screen.h file

disk.asm

global _readd

_readd:
 push eax
 push ebx
 push ecx
 push edx
 push ebp

 mov ebp, esp
 mov eax, [ebp+8]
 mov ecx, eax
 cmp ecx, 256
 jg short _fail
 jne short _good

_fail:
 xor eax, eax
 leave
 ret

_good:
 xor eax, eax
 mov eax, 12
 leave
 ret

It crashes when run it with VirtualBox. Any ideas?

Mat
  • 202,337
  • 40
  • 393
  • 406
C00LD0WN
  • 21
  • 2
  • 1
    *How* do you run it in VirtualBox? You might want to try it using [QEMU](http://wiki.qemu.org/Main_Page) which has hooks that allows you to use a debugger. – Some programmer dude Feb 18 '16 at 10:01
  • 2
    You don't use stack frames correctly. Read up how `ENTER` and `LEAVE` work. After your `leave`, you still have everything pushed on the stack. – ElderBug Feb 18 '16 at 10:11
  • I poped everything and it is always returning me error. When I change my sector to 25 it should return an int different than 0 but it is returning 0. What am I doing wrong? – C00LD0WN Feb 18 '16 at 10:40
  • I had to ovewrite registers. – C00LD0WN Feb 18 '16 at 10:52
  • 2
    `mov eax, [ebp+8]` is essentially a `mov eax, ecx`. You screwed up the stack setup dude. – Margaret Bloom Feb 18 '16 at 11:20
  • 1
    See the [x86 tag wiki](http://stackoverflow.com/tags/x86/info) for links to calling conventions. You only need to save/restore some of the regs you use. But more importantly, you have to actually `pop` them, in reverse order to the order you pushed, so the data comes back off the stack into the original locations. You could also simplify the branching by conditionally jumping over `mov eax, 12`. The good/fail paths are the same after that, and can rejoin each other without any jumps. You *don't* need to make a traditional `enter` / `leave` stack frame, and use `[esp + offset]` for the arg – Peter Cordes Feb 18 '16 at 11:20

1 Answers1

2

If you save CPU registers when you enter a function, you need to restore them when you are finished. Your PUSHs need to be matched with POPs.

Also, if you use a stack frame to access local variables and parameters, setup the frame (push ebp ; mov ebp, esp) before everything, so you can more easily refer to them. Here [ebp+8] doesn't refer to a parameter, because you alter the stack before setting up the frame.

ElderBug
  • 5,926
  • 16
  • 25
  • You should not use `enter` either. – Ven Feb 18 '16 at 11:42
  • 1
    @Ven Why not ? OP **did** use a stack frame, so I explain how to do it correctly. The fact that you can do everything without a stack frame is irrelevant. – ElderBug Feb 18 '16 at 11:54
  • No, that's not what I'm talking about. [see this](http://stackoverflow.com/a/26323663/1737909) – Ven Feb 18 '16 at 11:59
  • 1
    @Ven That's even worse. Downvoting for a minor performance detail isn't really useful. Anyway, edited the answer to focus more on OP' problem, and didn't mention `enter`. – ElderBug Feb 18 '16 at 12:23
  • it's "obsolete but are still supported for backwards compatibility reasons". anyway, removed my downvote, as it's not relevant anymore. – Ven Feb 18 '16 at 13:22
  • @Ven I'm curious if there is any official statement that `enter` is obsolete/not recommended. `leave` is widely used, and it doesn't make any sense to obsolete only half of an instruction pair. Do you have any source in mind ? About the downvote, your comments are welcome, it's just that I think it's not good to downvote when it doesn't challenge the answer at any point. – ElderBug Feb 18 '16 at 13:33