Page 1 of 1

Invalid opcodes

Posted: Fri Oct 17, 2008 10:40 am
by souradipm
Hi there,
I will probably sound stupid, but i have been getting invalid opcode exceptions. I'm sure it's due to my dodge jmping, as i am implementing app loading.
GRUB loads it as a module and I jump to it. However, while jmping, my exception prints out an invalid opcode exception error. Please help.

Code:

Code: Select all

if(mb->mods_count>0){
        con_print("Jumping to loaded app...");
	_asm_jmp(&mb->mods_addr);
	con_print("\nThis shouldnt be displayed - _exit system call forwards execution somewhere else");
	}
(C calling the asm code)
The prototype for _asm_jmp is:

Code: Select all

extern void _asm_jmp(uint32_t*);
and the pure asm binary which utilises my kernel's system calls is:

Code: Select all

[BITS 32]

%include "../lib/libretasm/lib.asm"

main:
mov ebx, str1
call con_print
call getch
call _exit
cli
hlt

.data
str1 db "Yay! This is from an app loaded by Retix!!!\n\nPress any key to exit."
While the lib file is:

Code: Select all

; ASM Syscall wrappers

; con_print
; IN  : ebx - String to print
; OUT : none

con_print:
	mov eax, 0
	int 0x80
	ret

; getch
; IN  : none
; OUT : none

getch:
	mov eax, 5
	int 0x80
	ret

; malloc
; IN  : ebx - amount
; OUT : eax - location

malloc:
	mov eax, 1
	int 0x80
	
; malloc
; IN  : ebx - location
; OUT : none

free:
	mov eax, 7
	int 0x80
	
; con_put
; IN  : ebx - char
; OUT : none

con_put:
	mov eax, 1
	int 0x80

; _exit
; IN  : none
; OUT : none

_exit:
	mov eax, 13
	int 0x80
If you need any more info just ask. The command for compiling test.asm into test.bin which is loaded by GRUB is:

Code: Select all

nasm -fbin -o test.bin test.asm
Thanks in advance,
~souradipm

Re: Invalid opcodes

Posted: Fri Oct 17, 2008 1:15 pm
by AJ
Hi,

The lib file is included at the start of you main ASM file, meaning that the entry point is, in effect, con_print. The ret instruction at the end of con_print will return to an invalid location because you haven't got a valid return address on the stack.

Simple solution: Move the %include to the end of the file.

More complex, long term solution: Support a formatted executable such as ELF which defines a specific entry point.

Cheers,
Adam

Re: Invalid opcodes

Posted: Fri Oct 17, 2008 1:46 pm
by souradipm
Thanks, AJ for your suggestion.
However, it still throws an invalid opcode exception. I think I forgot to add the _asm_jmp code, which may be the problem.

Code: Select all

;Using __asm_jmp so C can use it as _asm_jmp (using DJGPP)
[global __asm_jmp]
__asm_jmp:
	jmp ebx
	ret ;Shouldnt be called, but for uniformity's sake, it just feels right :P
	
I am trying to get basic app loading working first, before I move onto supporting file formats such as elf. It is why i have made the test app a pure binary file

Thanks anyway, AJ, and I hope it will prevent problems in the future,
souradipm

Re: Invalid opcodes

Posted: Sat Oct 18, 2008 6:24 am
by souradipm
Ah, found the problem - I added a pop ebx before the jmp ebx and it doesnt throw up an exception. However, it doesnt work either. It calls 'con_print("\nThis shouldnt be displayed - _exit system call forwards execution somewhere else");' so it doesn't jump to the loaded module. Can anyone help with this new problem, please?

~souradipm

Re: Invalid opcodes

Posted: Sat Oct 18, 2008 8:30 am
by ru2aqare
I would use something like

Code: Select all

; C prototype
; void jump_to_target(void* target)
jump_to_target proc near
    jmp    dword ptr [esp +4]
jump_to_target endp
An additional benefit of this is that you can adapt it to have arbitrary parameters, and would still work:

Code: Select all

; C prototype
; void jump_to_target_ex(void* target, ...)
jump_to_target_ex proc near
    mov   eax, dword ptr [esp +4] ; load target
    mov   ecx, dword ptr [esp +0] ; load return address
    mov   dword ptr [esp +0], eax
    mov   dword ptr [esp +4], ecx
    retn  ; since target is at [esp+0], this pops the extra argument off the stack, and jump to the intended location
jump_to_target_ex endp

Writing

Code: Select all

jump_to_target proc near
    pop    ebx
    jmp    ebx
jump_to_target endp
is equivalent to writing

Code: Select all

jump_to_target proc near
    retn
jump_to_target endp
Edit: the above code assumes your compiler does not use a fastcall-like mechanism, and passes all arguments on the stack. Most compilers for x86 do this, as far as I know.

Re: Invalid opcodes

Posted: Mon Oct 20, 2008 5:43 am
by jal
souradipm wrote:Can anyone help with this new problem, please?
Please, please, please use bochs with the debugger. It is so much easier to pin down errors, and you can actually find them yourself instead of bugging the forum. Put a breakpoint on the jmp instruction, single step, and lo and behold the next instruction. Is it the one you wanted? And look at the address, is it the address you expect? Disassemble the address you think your module is - is it really there? Etc. etc. etc. Within a few minutes time you'll have tracked down all of the problems you face, instead of days on this forum.


JAL