Invalid opcodes

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
souradipm
Posts: 22
Joined: Fri Aug 15, 2008 10:08 am

Invalid opcodes

Post 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
User avatar
AJ
Member
Member
Posts: 2646
Joined: Sun Oct 22, 2006 7:01 am
Location: Devon, UK
Contact:

Re: Invalid opcodes

Post 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
souradipm
Posts: 22
Joined: Fri Aug 15, 2008 10:08 am

Re: Invalid opcodes

Post 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
souradipm
Posts: 22
Joined: Fri Aug 15, 2008 10:08 am

Re: Invalid opcodes

Post 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
ru2aqare
Member
Member
Posts: 342
Joined: Fri Jul 11, 2008 5:15 am
Location: Hungary

Re: Invalid opcodes

Post 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.
jal
Member
Member
Posts: 1385
Joined: Wed Oct 31, 2007 9:09 am

Re: Invalid opcodes

Post 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
Post Reply