By incrementally changing instructions in an assembly language, it is possible to build up a picture of how the bytes relate to the assembly instructions (without going to the trouble of actually reading the documentation). Note that, for these trivial examples at least, there is no difference between the binaries generated by NASM and the equivalent MS Debug instructions.
NASM version 0.98.39 compiled on Feb 25 2005
DOS, 16bit, x86
;nasm ;bytes
org 100h ;address
mov ax,1234h ;B8 34 12
mov ax,bx ;89 D8
int 20h ;CD 20
;nasm ;bytes
org 100h ;address
mov ax,1234h ;B8 34 12
mov bx,ax ;89 C3
int 20h ;CD 20
;nasm ;bytes
org 100h ;address
mov ax,1234h ;B8 34 12
mov ax,cx ;89 C8
mov ax,bx ;89 D8
int 20h ;CD 20
Generating Your Own Binaries
;nasm ;bytes
org 100h ;address
mov ax,0200h ;B8 00 02
mov dx,0041h ;BA 41 00
int 21h ;CD 21
int 20h ;CD 20
The above code emits the character 'A' (
explanation of the code). This information can be used as a template for generating a working binary. The Java program
GenExecutable
(listing below) generates a DOS executable that prints a string.
In the example usage below, it generates an identical binary to the one made by NASM.
C:\test>java -cp .\bin GenExecutable "A"
Writing MADEbyJAVA.COM
C:\test>PrintHex.exe -h MADEbyJAVA.COM
B8 00 02 BA 41 00 CD 21 CD 20 ____A__!_
C:\test>MADEbyJAVA.COM
A
Here is Hello, World!
C:\test>java -cp .\bin GenExecutable "Hello, World!"
Writing MADEbyJAVA.COM
C:\test>PrintHex -h MADEbyJAVA.COM
B8 00 02 BA 48 00 CD 21 B8 00 02 BA 65 00 CD 21 ____H__!____e__!
B8 00 02 BA 6C 00 CD 21 B8 00 02 BA 6C 00 CD 21 ____l__!____l__!
B8 00 02 BA 6F 00 CD 21 B8 00 02 BA 2C 00 CD 21 ____o__!____,__!
B8 00 02 BA 20 00 CD 21 B8 00 02 BA 57 00 CD 21 ____ __!____W__!
B8 00 02 BA 6F 00 CD 21 B8 00 02 BA 72 00 CD 21 ____o__!____r__!
B8 00 02 BA 6C 00 CD 21 B8 00 02 BA 64 00 CD 21 ____l__!____d__!
B8 00 02 BA 21 00 CD 21 CD 20 ____!__!_
C:\test>MADEbyJAVA.COM
Hello, World!
Listing: GenExecutable.java
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* Generates a DOS program called "MADEbyJAVA.COM"
* @author McDowell
*/
public class GenExecutable {
public static void main(String[] args) {
if(args.length!=1) {
System.out.println("Usage: java GenExecutable <string>");
return;
}
try {
writePrintAExecutable(args[0]);
} catch(IOException e) {
e.printStackTrace();
}
}
private static void writePrintAExecutable(String str) throws IOException {
final String filename = "MADEbyJAVA.COM";
System.out.println("Writing "+filename);
OutputStream out = new FileOutputStream(filename);
try {
for(int i=0; i<str.length(); i++) {
char ch = str.charAt(i);
writePrintCharacter(out, (byte) ch);
}
writeTerminate(out);
} finally {
out.close();
}
}
/**Instruction: write a character to the console*/
private static void writePrintCharacter(OutputStream out, byte charByte) throws IOException {
final byte INTERRUPT = (byte) 0xCD;
final byte FUNCTION = (byte) 0x21;
final byte ZERO = (byte) 0x00;
final byte SUB_FUNCTION_2 = (byte) 0x02;
setAX(out, SUB_FUNCTION_2, ZERO);
setDX(out, ZERO, charByte);
//int 21
out.write(INTERRUPT);
out.write(FUNCTION);
}
/**Instruction: end program*/
private static void writeTerminate(OutputStream out) throws IOException {
final byte INTERRUPT = (byte) 0xCD;
final byte FUNCTION_TERMINATE = (byte) 0x20;
//int 20
out.write(INTERRUPT);
out.write(FUNCTION_TERMINATE);
}
/**Instruction: set value of register AX*/
private static void setAX(OutputStream out, byte ah, byte al) throws IOException {
final byte MOV_AX = (byte) 0xB8;
//mov ax,ahal
out.write(MOV_AX);
out.write(al);
out.write(ah);
}
/**Instruction: set value of register DX*/
private static void setDX(OutputStream out, byte dh, byte dl) throws IOException {
final byte MOV_DX = (byte) 0xBA;
//mov dx,dhdl
out.write(MOV_DX);
out.write(dl);
out.write(dh);
}
}
|
kewl :)
ReplyDelete