How to make the DOS .exe relocation table smaller with OpenWatcom linker? - exe

I've created the following DOS .exe file with OpenWatcom:
$ xxd prog.exe
00000000: 4d5a 8200 0100 0100 0300 4000 ffff 0500 MZ........#.....
00000010: 0204 0000 0000 0000 2000 0000 0000 0000 ........ .......
00000020: 0100 0000 0000 0000 0000 0000 0000 0000 ................
00000030: b804 008e d8e8 0900 b44c cd21 d1e2 01d0 .........L.!....
00000040: c353 52ba 0200 b409 cd21 ba0c 00b4 09cd .SR......!......
00000050: 21ba 0f00 b409 cd21 ba08 00b8 0700 e8db !......!........
00000060: ff89 c3ba 0a00 b809 00e8 d0ff 01d8 5a5b ..............Z[
00000070: c300 4865 6c6c 6f21 0d0a 2400 6162 0063 ..Hello!..$.ab.c
00000080: 6400 d.
Regions:
0x0...0x1c: DOS .exe header.
0x1c...0x20: 4 bytes of padding.
0x20...0x24: 4 bytes containing 1 relocation entry.
0x24...0x30: 12 bytes of padding.
0x30...: code (_TEXT) segment with 16-bit 8086 machine code.
...
How do I get rid of the 4 bytes of padding and the 12 bytes of padding, so that the code starts at offset 0x20? Is there a WLINK flag for this? Should I use a different linker? Should I post-process the generated .exe?

I wasn't able to find a configuration option for this, so I ended up writing my own linker and using it instead of WLINK. This way the .exe header became only 24 (0x18) bytes, and I didn't need any relocations.

Related

elf aarch64 golfed with sys_write

To better understand the ELF format and the ARM aarch64, I'm trying to create my elf binary without compilers, just echoing bytes with bash.
Will can see my effort here: http://www.github.com/glaudiston/elf
I have succeeded in achieving a fully working elf with sys_write and sys_exit syscalls for x64.
But for aarch64, it's not working as I expect it to:
# cat make-elf.sh
#!/bin/bash
#
# depends on:
# - elf_fn.sh (github.com/glaudiston/elf)
# - base64 (gnu-coreutils)
#
. elf_fn.sh
instructions="";
instructions="${instructions}\nwrite $(echo -en "hello world\n" | base64 -w0)";
instructions="${instructions}\nexit 3";
write_elf elf "${instructions}";
It generates:
$ xxd elf
00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000 .ELF............
00000010: 0200 b700 0100 0000 7800 0100 0000 0000 ........x.......
00000020: 4000 0000 0000 0000 0000 0000 0000 0000 #...............
00000030: 0000 0000 4000 3800 0100 0000 0000 0000 ....#.8.........
00000040: 0100 0000 0500 0000 0000 0000 0000 0000 ................
00000050: 0000 0100 0000 0000 0000 0000 0000 0000 ................
00000060: 7800 0000 0000 0000 7800 0000 0000 0000 x.......x.......
00000070: 0000 0000 0000 0000 2000 80d2 010c 0058 ........ ......X
00000080: 8201 80d2 0808 80d2 0100 00d4 6000 80d2 ............`...
00000090: a80b 80d2 0100 00d4 6865 6c6c 6f20 776f ........hello wo
000000a0: 726c 640a
$ ./make-elf.sh 0 && ./elf; echo $?
3
$ cat elf | base64 -w0; echo
f0VMRgIBAQAAAAAAAAAAAAIAtwABAAAAeAABAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAOAABAAAAAAAAAAEAAAAFAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAeAAAAAAAAAB4AAAAAAAAAAAAAAAAAAAAIACA0gEMAFiCAYDSCAiA0gEAANRgAIDSqAuA0gEAANRoZWxsbyB3b3JsZAo=
It returns the expected exit code, with no illegal exceptions, but the sys_write call is not printing anything.
Hiding all ELF overhead, we have this:
00000078: 2000 80d2 010c 0058 ......X
00000080: 8201 80d2 0808 80d2 0100 00d4 6000 80d2 ............`...
00000090: a80b 80d2 0100 00d4 6865 6c6c 6f20 776f ........hello wo
000000a0: 726c 640a rld.
The exit call is working as expected, so I can hide it too:
00000078: 2000 80d2 010c 0058 ......X
00000080: 8201 80d2 0808 80d2 0100 00d4 ............
00000090: 6865 6c6c 6f20 776f hello wo
000000a0: 726c 640a rld.
So we have the data hello world.\n starting at position 98. I am very confused about how to do the sys_write call here. In x64 I can set to the next data address that in this case should be 65688(composed of PH_VADDR_V(65536) + ELF_HEADER_SIZE(64) + ELF_BODY_SIZE(32) (without DATA_SECTION)")
To the output fd I do set in r0 the value 1 with 2000 80d2
To the data address I am using 010c that is little endian representation of 0c01 this bits: 00001100000 00001 The last 5 bits are the r1 register, used to data address.
Given I only have 11 bits
Here I've used the LDR (0058) but I've tried MOV (here 80d2) too. With no success
I've tried any value from 0 to 2048 where it starts to reports Illegal instruction and exit code 132.
I think maybe aarch64 does not allow the same trick I've used in x64 to print data without a labeled data section. I'll work on creating it, but this is just a guess and I really want to understand why this is not printing nothing.
So, your string is at absolute address 0x10098 and you need to get this address into the x1 register.
First of all, LDR is not what you want. It is, as the name suggests, a load (read) from memory. You don't want your instruction to access memory at all, it just wants to put the value 0x10098 into the register.
MOV is closer, which writes an immediate value into the register, but the problem is that the immediate is limited to 16 bits, and you need 17. Because instructions are 32 bits, there are only so many bits available for an immediate. My guess is that you overflowed this and ended up changing opcode bits instead, so you encoded a totally different instruction. (Don't guess at encodings! Look them up. This would have shown you the 16-bit limit.)
For getting arbitrary immediate values into a register, the intended approach is a sequence of MOV/MOVK instructions to write 16 bits at a time. Here you would just need two of them:
0: d2801301 mov x1, #0x98 // #152
4: f2a00021 movk x1, #0x1, lsl #16
Though since we are using a extra word, the address of the string will also shift, so you'd have to adjust accordingly.
However, for addresses in particular, AArch64 provides pc-relative address generation instructions, ADR/ADRP. These let you add an immediate value to the current value of the program counter (i.e. the address of the currently executing instruction) and write the result to a register. As a bonus, they allot more bits for the immediate (though you will no longer need them).
Here we can use ADR. Its opcode is 0 at bit 31, and 10000 at bits 24-28. The destination register is bits 0-4, we want 00001. The immediate gets its low two bits at bits 29-30, and the higher bits at 5-23. The ADR instruction will be at absolute address 0x1007c and we want 0x10098, so the displacement is 0x1c = 0b11100. Thus the encoding we want is
0 00 10000 0000000000000000111 00001 = 0x100000e1
Some general tips:
Try writing code with an assembler first, so that you can learn the instruction set and be able to focus on experimenting with what the instructions do, instead of also getting bogged down in how they are encoded. If you want to come back and do the encoding by hand later, fine, but with an assembler you'll also have a way to check your work.
Use a debugger to single-step your program. That would have showed you that your LDR was giving you a totally bogus value and might have been a hint that it didn't do what you think it did.
Use strace to see what system calls your program makes. That would show you (I think, I didn't test) that write does get invoked but with the wrong address.

Is there a way to exploit BitBoard advantages on a 4x16 gameboard?

So basically the title. The gameboard looks like this:
0000 0000 0000 0000
0000 0000 0000 0000
0000 0000 0000 0000
0000 0000 0000 0000
I cant wrap my head around, if it is possible to use the BitBoard logic on this kind of board?
If it is possible is there an advantage doing it?
Or can BitBoard logic only be used for square boards ?

Python stops binary reading of file after getting byte 0xa or 0xd

I want to read some binary file. It is a big file so i use maximalOffset variable to stop reading after getting to it. But reading is always ends at one offset - 8199. The last byte i get is 0xa. In xxd it is the part of byte 0a0d.
I am using Ubuntu 18 and Python 3.
I found some info about 0x1A in Windows (it's EOF symbol or something) but the solution was to use binary reading and 0xA is not 0x1A...
maximalOffsetString = "2070"
maximalOffset=int(maximalOffsetString,16)
offset=-16 # first 16 bytes must be on 0x0 offset
line = [ ]
pagefile = open("./pagefile", "rb")
for bytes in pagefile:
for byte in bytes:
if maximalOffset==offset: break
if len(line) == 16:
print(hex(offset))
print(str(offset)+" : "+str(maximalOffset))
print(line)
del line[:]
line.append(hex(byte))
offset=offset+1
break
pagefile.close()
# here i see what was the last symbols in array:
print(hex(offset))
print(str(offset)+" : "+str(maximalOffset))
print(line)
Output:
0x2007
8199 : 8304
['0xf0', '0xa9', '0xc', '0x7', '0x71', '0xc0', '0xa']
as you can see, my maximalOffset is 8304 but the reading stops at 8199. In xxd this line is:
00002010: f0a9 0c07 71c0 0a0d 0000 006c 0105 5c00
All file before this is only zeros. After 0x2000 there are random bytes.
00001fb0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00001fc0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00001fd0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00001fe0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00001ff0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00002000: 0104 0000 6f01 005c 0094 008c e026 6469 ....o..\.....&di
00002010: f0a9 0c07 71c0 0a0d 0000 006c 0105 5c00 ....q......l..\.
00002020: 9500 8c20 b800 8040 0001 10ab 0c07 4230 ... ...#......B0
00002030: 0dba 0069 010a 5c00 9600 8ce8 b800 38a7 ...i..\.......8.
00002040: 0c07 fbd0 7b01 6601 0f5c 0097 0008 0020 ....{.f..\.....
00002050: 208c f8b8 0090 940d 0724 0000 7a01 6301 ........$..z.c.
00002060: 0c5c 0098 008c 0027 6469 9892 0d07 f2b9 .\.....'di......
00002070: 0009 0080 4100 4100 6001 115c 0099 008c ....A.A.`..\....
00002080: 08b8 0020 0d0e 072b 7c01 7d01 165c 009a ... ...+|.}..\..
00002090: 008c 10b8 0028 a20c 0727 bc00 8100 4200 .....(...'....B.
000020a0: 7a01 1b5c 009b 008c 18b9 009f 0d07 29bc z..\..........).
000020b0: 0077 0118 5c00 9c00 8c98 b803 6091 0d07 .w..\.......`...
000020c0: 06b0 3b05 4000 0103 7401 1d5c 009d 7801 ..;.#...t..\..x.
000020d0: b800 208f 0d07 10f0 097a 0471 0122 5c00 .. ......z.q."\.
I think you are breaking the outer for loop before reading is finished, remove break at the bottom of the outer for loop.
...
for bytes in pagefile:
for byte in bytes:
...
line.append(hex(byte))
offset=offset+1
break # <- Remove this
pagefile.close()
...

Bash: How to detect multimedia keypresses in a shell script?

So I've been working on a old kobo ereader(No touch screen) and I've been trying to figure out how to detect when the buttons on it are pressed.
So far I've used hexdump to figure out the keycodes, but they don't work like a regular keyboard in that showkey doesn't work on them. Here's the hexdump output I got for the buttons:
hexdump /dev/input/event0
upPress 0000000 fc92 5512 92dd 0003 0001 0067 0001 0000
upRelease 0000010 fc92 5512 7905 0006 0001 0067 0000 0000
rightPress 0000020 fcab 5512 0cec 000b 0001 006a 0001 0000
rightRelease 0000030 fcab 5512 7de5 000d 0001 006a 0000 0000
downPress 0000040 fcb6 5512 48eb 0001 0001 006c 0001 0000
downRelease 0000050 fcb6 5512 b9e4 0003 0001 006c 0000 0000
leftPress 0000060 fcc0 5512 2b98 000f 0001 0069 0001 0000
leftRelease 0000070 fcc1 5512 3342 0002 0001 0069 0000 0000
middlePress 0000080 fccd 5512 acaa 0000 0001 001c 0001 0000
middleRelease 0000090 fccd 5512 1da4 0003 0001 001c 0000 0000
I've determined from this that the keycodes are the 7th number, so 0x67 for example. The only problem I have now is I can't figure out how to detect those in a shell script.
This has got me stumped, right now the device has Linux 2.6.28, Busybox v1.17.1 and a few other programs. It is connected to the internet though, so I might be able to install some stuff, but there's no package manager so I'd prefer not to.
Edit: Stuff I've tried -
Read doesn't work, atleast the way I'm using it.
#!/bin/bash
read -n 1 -s key
echo "key pressed:" $key
Lots of Google searches - most of them require X, which I don't have. The bind command might work, but I don't have it on the system.
Edit 2: More things -
More research has pointed me to the cat command, it shows the output from the keys in a weird code like this:
cat /dev/input/event0
T)U┐Ä☺g☺T)Utè☺gW)U╗☺l☺W)Uúp
☺lY)U3⌐
☺l☺Y)U"☺lZ)Uë"
☺l☺Z)Uæ║
☺l\)U║╙☺i☺\)U▓D♥☺i
Unfortunately it looks like it's different every time, so I don't know how to make sense of it.

Transforming a binary file into a decimal format using bash, how to?

I have a binary file generated by my program, but I need to compare its decimal contents to check if they meet my requirements. However, I can't seem to find a way to do this using bash, is there any code that lets me get this done? Whenever I open it using a program like sublime text I get the contents in HEX form; however, I am not looking for that.
5249 4646 5200 0000 5741 5645 666d 7420
1000 0000 0100 0200 44ac 0000 10b1 0200
0400 1000 6461 7461 2e00 0000 0200 0200
0200 0300 0300 0900 0900 0900 0c00 0c00
1400 1400 1400 1800 1800 0c00 0c00 0c00
0600 0600 0200 0200 0200
For a dump of bytes in decimal:
od -t u1 filename
For a dump of 2-byte words in decimal:
od -t u2 filename
In bash, simply type
xxd -b yourbinaryfile

Resources