Hi everyone,
I'm trying to use a short relative jump to conditionally skip over a known sequence of instructions. I've calculated that the offset should be 30 bytes (0x1e), given the code and disassembly output below. I want it to jump from from 0x100D to 0x102D, and the offset should be relative to the instruction after the jump instruction (0x100F), so 0x102D - 0x100F = 0x1e.
When I write "jne short 0x1e" and compile the program with NASM, this becomes 751D (jnz +0x1d) and the offset is 1 byte too small. I have no idea why this happens. It work if I instead write "jne short $ + 0x20", which only confuses me more. If anyone could explain why "jne short 0x1e" only jumps by 0x1d bytes, I'd greatly appreciate it!
Here's the complete code:
section .data
SYS_EXIT equ 60
EXIT_CODE equ 0
READ equ 0
WRITE equ 1
STDIN equ 0
STDOUT equ 1
IOCTL equ 16
FDFLUSH equ 10
section .bss
tape: resb 32768
must_flush: resb 1
section .text
global _start
_start:
mov rbx, 0
cmp [must_flush], byte 1
jne short 0x1e // Jump from here
mov rax, IOCTL
mov rdi, STDOUT
mov rsi, FDFLUSH
mov rdx, 0
syscall
mov [must_flush], byte 0
mov rax, READ // Jump to here
mov rdi, STDIN
mov rsi, tape
add rsi, rbx
mov rdx, 1
syscall
_exit:
mov rax, SYS_EXIT
mov rdi, EXIT_CODE
syscall
And here's what I get when I run ndisasm on the compiled program:
00000FFF 00BB00000000 add [rbx+0x0],bh
00001005 803C2500A0400001 cmp byte [0x40a000],0x1
0000100D 751D jnz 0x102c // This should jump to 0x102D
0000100F B810000000 mov eax,0x10
00001014 BF01000000 mov edi,0x1
00001019 BE0A000000 mov esi,0xa
0000101E BA00000000 mov edx,0x0
00001023 0F05 syscall
00001025 C6042500A0400000 mov byte [0x40a000],0x0
0000102D B800000000 mov eax,0x0
00001032 BF00000000 mov edi,0x0
00001037 48BE002040000000 mov rsi,0x402000
-0000
00001041 4801DE add rsi,rbx
00001044 BA01000000 mov edx,0x1
00001049 0F05 syscall
0000104B B83C000000 mov eax,0x3c
00001050 BF00000000 mov edi,0x0
00001055 0F05 syscall