├── .gitignore ├── README.md ├── Vagrantfile ├── euclid ├── README.md ├── asm_io.inc ├── asm_io.o ├── cdecl.h ├── driver.c └── euclid.asm ├── examples ├── README.md ├── borland-ex.zip ├── borland │ ├── Makefile │ ├── array1.asm │ ├── array1c.c │ ├── asm_io.asm │ ├── asm_io.inc │ ├── asm_io.obj │ ├── big_int.cpp │ ├── big_int.hpp │ ├── big_math.asm │ ├── bitcount.c │ ├── bitcount2.c │ ├── cdecl.h │ ├── dmax.asm │ ├── dmaxt.c │ ├── driver.c │ ├── first.asm │ ├── fprime.c │ ├── main4.asm │ ├── main5.c │ ├── main6.c │ ├── math.asm │ ├── max.asm │ ├── memex.c │ ├── memory.asm │ ├── prime.asm │ ├── prime2.asm │ ├── quad.asm │ ├── quadt.c │ ├── read.asm │ ├── readt.c │ ├── skel.asm │ ├── sub1.asm │ ├── sub2.asm │ ├── sub3.asm │ ├── sub4.asm │ ├── sub5.asm │ ├── sub6.asm │ └── test_big_int.cpp ├── cygwin-ex.zip ├── cygwin │ ├── Makefile │ ├── array1.asm │ ├── array1c.c │ ├── asm_io.asm │ ├── asm_io.inc │ ├── asm_io.o │ ├── big_int.cpp │ ├── big_int.hpp │ ├── big_math.asm │ ├── bitcount.c │ ├── bitcount2.c │ ├── cdecl.h │ ├── dmax.asm │ ├── dmaxt.c │ ├── driver.c │ ├── first.asm │ ├── fprime.c │ ├── main4.asm │ ├── main5.c │ ├── main6.c │ ├── math.asm │ ├── max.asm │ ├── memex.c │ ├── memory.asm │ ├── prime.asm │ ├── prime2.asm │ ├── quad.asm │ ├── quadt.c │ ├── read.asm │ ├── readt.c │ ├── skel.asm │ ├── sub1.asm │ ├── sub2.asm │ ├── sub3.asm │ ├── sub4.asm │ ├── sub5.asm │ ├── sub6.asm │ └── test_big_int.cpp ├── djgpp-ex.zip ├── djgpp │ ├── Makefile │ ├── array1.asm │ ├── array1c.c │ ├── asm_io.asm │ ├── asm_io.inc │ ├── asm_io.o │ ├── big_int.cpp │ ├── big_int.hpp │ ├── big_math.asm │ ├── bitcount.c │ ├── bitcount2.c │ ├── cdecl.h │ ├── dmax.asm │ ├── dmaxt.c │ ├── driver.c │ ├── first.asm │ ├── fprime.c │ ├── main4.asm │ ├── main5.c │ ├── main6.c │ ├── math.asm │ ├── max.asm │ ├── memex.c │ ├── memory.asm │ ├── prime.asm │ ├── prime2.asm │ ├── quad.asm │ ├── quadt.c │ ├── read.asm │ ├── readt.c │ ├── skel.asm │ ├── sub1.asm │ ├── sub2.asm │ ├── sub3.asm │ ├── sub4.asm │ ├── sub5.asm │ ├── sub6.asm │ └── test_big_int.cpp ├── linux-ex.zip ├── linux │ ├── Makefile │ ├── array1.asm │ ├── array1c.c │ ├── asm_io.asm │ ├── asm_io.inc │ ├── asm_io.o │ ├── big_int.cpp │ ├── big_int.hpp │ ├── big_math.asm │ ├── bitcount.c │ ├── bitcount2.c │ ├── cdecl.h │ ├── dmax.asm │ ├── dmaxt.c │ ├── driver.c │ ├── first.asm │ ├── fprime.c │ ├── main4.asm │ ├── main5.c │ ├── main6.c │ ├── math.asm │ ├── max.asm │ ├── memex.c │ ├── memory.asm │ ├── prime.asm │ ├── prime2.asm │ ├── quad.asm │ ├── quadt.c │ ├── read.asm │ ├── readt.c │ ├── skel.asm │ ├── sub1.asm │ ├── sub2.asm │ ├── sub3.asm │ ├── sub4.asm │ ├── sub5.asm │ ├── sub6.asm │ └── test_big_int.cpp ├── ms-ex.zip ├── ms │ ├── Makefile │ ├── array1.asm │ ├── array1c.c │ ├── asm_io.asm │ ├── asm_io.inc │ ├── asm_io.obj │ ├── big_int.cpp │ ├── big_int.hpp │ ├── big_math.asm │ ├── bitcount.c │ ├── bitcount2.c │ ├── cdecl.h │ ├── dmax.asm │ ├── dmaxt.c │ ├── driver.c │ ├── first.asm │ ├── fprime.c │ ├── main4.asm │ ├── main5.c │ ├── main6.c │ ├── math.asm │ ├── max.asm │ ├── memex.c │ ├── memory.asm │ ├── prime.asm │ ├── prime2.asm │ ├── quad.asm │ ├── quadt.c │ ├── read.asm │ ├── readt.c │ ├── skel.asm │ ├── sub1.asm │ ├── sub2.asm │ ├── sub3.asm │ ├── sub4.asm │ ├── sub5.asm │ ├── sub6.asm │ └── test_big_int.cpp ├── watcom-ex.zip └── watcom │ ├── Makefile │ ├── array1.asm │ ├── array1c.c │ ├── asm_io.asm │ ├── asm_io.inc │ ├── asm_io.obj │ ├── big_int.cpp │ ├── big_int.hpp │ ├── big_math.asm │ ├── bitcount.c │ ├── bitcount2.c │ ├── cdecl.h │ ├── dmax.asm │ ├── dmaxt.c │ ├── driver.c │ ├── first.asm │ ├── fprime.c │ ├── main4.asm │ ├── main5.c │ ├── main6.c │ ├── math.asm │ ├── max.asm │ ├── memex.c │ ├── memory.asm │ ├── prime.asm │ ├── prime2.asm │ ├── quad.asm │ ├── quadt.c │ ├── read.asm │ ├── readt.c │ ├── skel.asm │ ├── sub1.asm │ ├── sub2.asm │ ├── sub3.asm │ ├── sub4.asm │ ├── sub5.asm │ ├── sub6.asm │ └── test_big_int.cpp └── newproject.sh /.gitignore: -------------------------------------------------------------------------------- 1 | .vagrant 2 | .DS_Store 3 | euclid/euclid 4 | euclid/euclid.o 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This repo holds practice and experimental programs written in NASM assembly for 2 | the x86 instruction architecture. 3 | 4 | About 5 | 6 | The projects in this repo are a combination of practice questions from the 7 | [PCASM Tutorial](http://www.drpaulcarter.com/pcasm/) and my projects from 8 | two semesters of Assembly taught at 9 | [BMCC](http://www.bmcc.cuny.edu/j2ee/index.jsp). The school projects were all 10 | ported from [MASM](http://www.masm32.com). The examples directory holds all the 11 | supporting source and include files needed to follow the PCASM tutorial. 12 | 13 | Environment 14 | 15 | All projects were built using the instructions in the comments at the top of 16 | each main asm file on a 32 bit Archlinux Virtualbox instance. The projects are 17 | written in NASM but are executed by a C driver program as outlined in the PCASM 18 | tutorial. 19 | 20 | Requirements 21 | 22 | * make 23 | * nasm 24 | * gcc 25 | 26 | References 27 | 28 | * http://www.drpaulcarter.com/pcasm/ 29 | * http://asm.sourceforge.net 30 | -------------------------------------------------------------------------------- /euclid/README.md: -------------------------------------------------------------------------------- 1 | # euclid 2 | -------------------------------------------------------------------------------- /euclid/asm_io.inc: -------------------------------------------------------------------------------- 1 | extern read_int, print_int, print_string 2 | extern read_char, print_char, print_nl 3 | extern sub_dump_regs, sub_dump_mem, sub_dump_math, sub_dump_stack 4 | 5 | %macro dump_regs 1 6 | push dword %1 7 | call sub_dump_regs 8 | %endmacro 9 | 10 | 11 | ; 12 | ; usage: dump_mem label, start-address, # paragraphs 13 | %macro dump_mem 3 14 | push dword %1 15 | push dword %2 16 | push dword %3 17 | call sub_dump_mem 18 | %endmacro 19 | 20 | %macro dump_math 1 21 | push dword %1 22 | call sub_dump_math 23 | %endmacro 24 | 25 | %macro dump_stack 3 26 | push dword %3 27 | push dword %2 28 | push dword %1 29 | call sub_dump_stack 30 | %endmacro -------------------------------------------------------------------------------- /euclid/asm_io.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/humanshell/assembly/474346d24ed2e2abb0e4edd9dc085e6b84104001/euclid/asm_io.o -------------------------------------------------------------------------------- /euclid/cdecl.h: -------------------------------------------------------------------------------- 1 | #ifndef CDECL_HEADER_FILE 2 | #define CDECL_HEADER_FILE 3 | 4 | /* 5 | * Define macros to specify the standard C calling convention 6 | * The macros are designed so that they will work with all 7 | * supported C/C++ compilers. 8 | * 9 | * To use define your function prototype like this: 10 | * 11 | * return_type PRE_CDECL func_name( args ) POST_CDECL; 12 | * 13 | * For example: 14 | * 15 | * int PRE_CDECL f( int x, int y) POST_CDECL; 16 | */ 17 | 18 | 19 | #if defined(__GNUC__) 20 | # define PRE_CDECL 21 | # define POST_CDECL __attribute__((cdecl)) 22 | #else 23 | # define PRE_CDECL __cdecl 24 | # define POST_CDECL 25 | #endif 26 | 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /euclid/driver.c: -------------------------------------------------------------------------------- 1 | #include "cdecl.h" 2 | 3 | int PRE_CDECL asm_main( void ) POST_CDECL; 4 | 5 | int main() 6 | { 7 | int ret_status; 8 | ret_status = asm_main(); 9 | return ret_status; 10 | } 11 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | The examples in this directory come from 2 | http://www.drpaulcarter.com/pcasm/#exampleCode and include .inc files 3 | containing helpful macros to make getting started with PC ASM and little 4 | easier. 5 | -------------------------------------------------------------------------------- /examples/borland-ex.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/humanshell/assembly/474346d24ed2e2abb0e4edd9dc085e6b84104001/examples/borland-ex.zip -------------------------------------------------------------------------------- /examples/borland/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Borland makefile 3 | # Use with make using the -ms switch 4 | # 5 | 6 | .SUFFIXES: 7 | .SUFFIXES: .obj .asm .cpp .c 8 | 9 | AS=nasm 10 | ASFLAGS= -f obj 11 | CFLAGS= 12 | CC=bcc32 13 | CXX=bcc32 14 | CXXFLAGS= 15 | 16 | .asm.obj: 17 | $(AS) $(ASFLAGS) $*.asm 18 | 19 | .cpp.obj: 20 | $(CXX) -c $(CXXFLAGS) $*.cpp 21 | 22 | .c.obj: 23 | $(CC) -c $(CFLAGS) $*.c 24 | 25 | all: prime.exe math.exe sub1.exe sub2.exe sub3.exe sub4.exe sub5.exe sub6.exe first.exe memex.exe dmaxt.exe asm_io.obj fprime.exe quadt.exe test_big_int.exe 26 | 27 | prime.exe: driver.obj prime.obj asm_io.obj 28 | $(CC) $(CFLAGS) -eprime.exe driver.obj prime.obj asm_io.obj 29 | 30 | math.exe : driver.obj math.obj asm_io.obj 31 | $(CC) $(CFLAGS) -emath.exe driver.obj math.obj asm_io.obj 32 | 33 | first.exe : driver.obj first.obj asm_io.obj 34 | $(CC) $(CFLAGS) -efirst.exe driver.obj first.obj asm_io.obj 35 | 36 | sub1.exe : driver.obj sub1.obj asm_io.obj 37 | $(CC) $(CFLAGS) -esub1.exe driver.obj sub1.obj asm_io.obj 38 | 39 | sub2.exe : driver.obj sub2.obj asm_io.obj 40 | $(CC) $(CFLAGS) -esub2.exe driver.obj sub2.obj asm_io.obj 41 | 42 | sub3.exe : driver.obj sub3.obj asm_io.obj 43 | $(CC) $(CFLAGS) -esub3.exe driver.obj sub3.obj asm_io.obj 44 | 45 | sub4.exe : driver.obj sub4.obj main4.obj asm_io.obj 46 | $(CC) $(CFLAGS) -esub4.exe driver.obj sub4.obj main4.obj asm_io.obj 47 | 48 | sub5.exe : main5.obj sub5.obj asm_io.obj 49 | $(CC) $(CFLAGS) -esub5.exe main5.obj sub5.obj asm_io.obj 50 | 51 | sub6.exe : main6.obj sub6.obj 52 | $(CC) $(CFLAGS) -esub6.exe main6.obj sub6.obj 53 | 54 | asm_io.obj : asm_io.asm 55 | $(AS) $(ASFLAGS) -d OBJ_TYPE asm_io.asm 56 | 57 | array1.exe : driver.obj array1.obj array1c.obj 58 | $(CC) $(CFLAGS) -earray1.exe array1.obj array1c.obj asm_io.obj 59 | 60 | memex.exe : memex.obj memory.obj 61 | $(CC) $(CFLAGS) -ememex.exe memex.obj memory.obj 62 | 63 | dmaxt.exe : dmaxt.obj dmax.obj 64 | $(CC) $(CFLAGS) -edmaxt.exe dmaxt.obj dmax.obj 65 | 66 | quadt.exe : quadt.obj quad.obj 67 | $(CC) $(CFLAGS) -equadt.exe quadt.obj quad.obj 68 | 69 | readt.exe : readt.obj read.obj 70 | $(CC) $(CFLAGS) -ereadt.exe readt.obj read.obj 71 | 72 | fprime.exe : fprime.obj prime2.obj 73 | $(CC) $(CFLAGS) -efprime.exe fprime.obj prime2.obj 74 | 75 | test_big_int.exe : test_big_int.obj big_int.obj big_math.obj 76 | $(CXX) $(CXXFLAGS) -etest_big_int.exe test_big_int.obj big_int.obj big_math.obj 77 | 78 | big_int.obj : big_int.hpp 79 | 80 | test_big_int.obj : big_int.hpp 81 | 82 | first.obj : asm_io.inc first.asm 83 | 84 | sub1.obj : asm_io.inc 85 | 86 | sub2.obj : asm_io.inc 87 | 88 | sub3.obj : asm_io.inc 89 | 90 | sub4.obj : asm_io.inc 91 | 92 | main4.obj : asm_io.inc 93 | 94 | driver.obj : driver.c 95 | 96 | 97 | clean : 98 | del *.obj -------------------------------------------------------------------------------- /examples/borland/array1c.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Driver file for array1.asm file 3 | */ 4 | 5 | #include 6 | 7 | #include "cdecl.h" 8 | 9 | int PRE_CDECL asm_main( void ) POST_CDECL; 10 | void PRE_CDECL dump_line( void ) POST_CDECL; 11 | 12 | int main() 13 | { 14 | int ret_status; 15 | ret_status = asm_main(); 16 | return ret_status; 17 | } 18 | 19 | /* 20 | * function dump_line 21 | * dumps all chars left in current line from input buffer 22 | */ 23 | void dump_line() 24 | { 25 | int ch; 26 | 27 | while( (ch = getchar()) != EOF && ch != '\n') 28 | /* null body*/ ; 29 | } 30 | 31 | -------------------------------------------------------------------------------- /examples/borland/asm_io.inc: -------------------------------------------------------------------------------- 1 | extern read_int, print_int, print_string 2 | extern read_char, print_char, print_nl 3 | extern sub_dump_regs, sub_dump_mem, sub_dump_math, sub_dump_stack 4 | 5 | %macro dump_regs 1 6 | push dword %1 7 | call sub_dump_regs 8 | %endmacro 9 | 10 | 11 | ; 12 | ; usage: dump_mem label, start-address, # paragraphs 13 | %macro dump_mem 3 14 | push dword %1 15 | push dword %2 16 | push dword %3 17 | call sub_dump_mem 18 | %endmacro 19 | 20 | %macro dump_math 1 21 | push dword %1 22 | call sub_dump_math 23 | %endmacro 24 | 25 | %macro dump_stack 3 26 | push dword %3 27 | push dword %2 28 | push dword %1 29 | call sub_dump_stack 30 | %endmacro -------------------------------------------------------------------------------- /examples/borland/asm_io.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/humanshell/assembly/474346d24ed2e2abb0e4edd9dc085e6b84104001/examples/borland/asm_io.obj -------------------------------------------------------------------------------- /examples/borland/bitcount.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* 4 | * function bit_count 5 | * Counts the number of bits on (i.e., = 1) in an unsigned int 6 | * (This code assumes that an int is 32-bits!) 7 | * Parameter: 8 | * x - number to count bits of 9 | * Return value: 10 | * number of bits on in x 11 | */ 12 | int bit_count(unsigned int x ) 13 | { 14 | static unsigned int mask[] = { 0x55555555, 15 | 0x33333333, 16 | 0x0F0F0F0F, 17 | 0x00FF00FF, 18 | 0x0000FFFF }; 19 | int i; 20 | int shift; /* number of positions to shift to right */ 21 | 22 | for( i=0, shift=1; i < 5; i++, shift *= 2 ) 23 | x = (x & mask[i]) + ( (x >> shift) & mask[i] ); 24 | return x; 25 | } 26 | 27 | 28 | int main() 29 | { 30 | unsigned int x; 31 | 32 | printf("Enter a number: "); 33 | scanf("%i", &x); 34 | printf("There are %d bits on in %X\n", bit_count(x), x); 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /examples/borland/bitcount2.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static unsigned char byte_bit_count[256]; /* lookup table */ 4 | 5 | void initialize_count_bits() 6 | { 7 | int cnt, i, data; 8 | 9 | for( i = 0; i < 256; i++ ) { 10 | cnt = 0; 11 | data = i; 12 | while( data != 0 ) { 13 | data = data & (data - 1); 14 | cnt++; 15 | } 16 | byte_bit_count[i] = cnt; 17 | printf("%d %d\n", i, byte_bit_count[i]); 18 | } 19 | } 20 | 21 | int count_bits( unsigned int data ) 22 | { 23 | const unsigned char * dword = ( unsigned char *) & data; 24 | 25 | return byte_bit_count[dword[0]] + byte_bit_count[dword[1]] + 26 | byte_bit_count[dword[2]] + byte_bit_count[dword[3]]; 27 | } 28 | 29 | int main() 30 | { 31 | unsigned int x; 32 | 33 | initialize_count_bits(); 34 | printf("Enter a number: "); 35 | scanf("%i", &x); 36 | printf("There are %d bits on in %X\n", count_bits(x), x); 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /examples/borland/cdecl.h: -------------------------------------------------------------------------------- 1 | #ifndef CDECL_HEADER_FILE 2 | #define CDECL_HEADER_FILE 3 | 4 | /* 5 | * Define macros to specify the standard C calling convention 6 | * The macros are designed so that they will work with all 7 | * supported C/C++ compilers. 8 | * 9 | * To use define your function prototype like this: 10 | * 11 | * return_type PRE_CDECL func_name( args ) POST_CDECL; 12 | * 13 | * For example: 14 | * 15 | * int PRE_CDECL f( int x, int y) POST_CDECL; 16 | */ 17 | 18 | 19 | #if defined(__GNUC__) 20 | # define PRE_CDECL 21 | # define POST_CDECL __attribute__((cdecl)) 22 | #else 23 | # define PRE_CDECL __cdecl 24 | # define POST_CDECL 25 | #endif 26 | 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /examples/borland/dmax.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: dmax.asm 5 | 6 | global _dmax 7 | 8 | 9 | 10 | segment _TEXT public align=1 class=CODE use32 11 | ; function _dmax 12 | ; returns the larger of its two double arguments 13 | ; C prototype 14 | ; double dmax( double d1, double d2 ) 15 | ; Parameters: 16 | ; d1 - first double 17 | ; d2 - second double 18 | ; Return value: 19 | ; larger of d1 and d2 (in ST0) 20 | 21 | ; next, some helpful symbols are defined 22 | 23 | %define d1 [ebp+8] 24 | %define d2 [ebp+16] 25 | 26 | _dmax: 27 | enter 0, 0 28 | 29 | fld qword d2 30 | fld qword d1 ; ST0 = d1, ST1 = d2 31 | fcomip st1 ; ST0 = d2 32 | jna short d2_bigger 33 | fcomp st0 ; pop d2 from stack 34 | fld qword d1 ; ST0 = d1 35 | 36 | d2_bigger: ; if d2 is bigger, nothing to do 37 | 38 | exit: 39 | leave 40 | ret 41 | 42 | 43 | -------------------------------------------------------------------------------- /examples/borland/dmaxt.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "cdecl.h" 4 | 5 | double PRE_CDECL dmax( double, double ) POST_CDECL; 6 | 7 | int main() 8 | { 9 | double d1, d2; 10 | 11 | printf("Enter two doubles: "); 12 | scanf("%lf %lf", &d1, &d2); 13 | 14 | printf("The larger of %g and %g is %g\n", d1, d2, dmax(d1,d2)); 15 | return 0; 16 | } 17 | 18 | -------------------------------------------------------------------------------- /examples/borland/driver.c: -------------------------------------------------------------------------------- 1 | #include "cdecl.h" 2 | 3 | int PRE_CDECL asm_main( void ) POST_CDECL; 4 | 5 | int main() 6 | { 7 | int ret_status; 8 | ret_status = asm_main(); 9 | return ret_status; 10 | } 11 | -------------------------------------------------------------------------------- /examples/borland/fprime.c: -------------------------------------------------------------------------------- 1 | /* 2 | * file: fprime.c 3 | * This program calculates prime numbers 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | #include "cdecl.h" 10 | 11 | /* 12 | * function find_primes 13 | * finds the indicated number of primes 14 | * Parameters: 15 | * a - array to hold primes 16 | * n - how many primes to find 17 | */ 18 | extern void PRE_CDECL find_primes( int * a, unsigned n ) POST_CDECL; 19 | 20 | int main() 21 | { 22 | int status; 23 | unsigned i; 24 | unsigned max; 25 | int * a; 26 | 27 | printf("How many primes do you wish to find? "); 28 | scanf("%u", &max); 29 | 30 | a = calloc( sizeof(int), max); 31 | 32 | if ( a ) { 33 | 34 | find_primes(a,max); 35 | 36 | /* 37 | * print out the last 20 primes found 38 | */ 39 | for(i= ( max > 20 ) ? max - 20 : 0; i < max; i++ ) 40 | printf("%3d %d\n", i+1, a[i]); 41 | 42 | free(a); 43 | status = 0; 44 | } 45 | else { 46 | fprintf(stderr, "Can not create array of %u ints\n", max); 47 | status = 1; 48 | } 49 | 50 | return status; 51 | } 52 | -------------------------------------------------------------------------------- /examples/borland/main4.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: main4.asm 5 | ; Multi-module subprogram example program 6 | ; 7 | ; To create executable: 8 | ; Using djgpp: 9 | ; nasm -f coff sub4.asm 10 | ; nasm -f coff main4.asm 11 | ; gcc -o sub4 sub4.o main4.o driver.c asm_io.o 12 | ; 13 | ; Using Borland C/C++ 14 | ; nasm -f obj sub4.asm 15 | ; nasm -f obj main4.asm 16 | ; bcc32 sub4.obj main4.asm driver.c asm_io.obj 17 | 18 | %include "asm_io.inc" 19 | 20 | segment _DATA public align=4 class=DATA use32 21 | sum dd 0 22 | 23 | segment _BSS public align=4 class=BSS use32 24 | input resd 1 25 | 26 | group DGROUP _BSS _DATA 27 | 28 | ; 29 | ; psuedo-code algorithm 30 | ; i = 1; 31 | ; sum = 0; 32 | ; while( get_int(i, &input), input != 0 ) { 33 | ; sum += input; 34 | ; i++; 35 | ; } 36 | ; print_sum(num); 37 | 38 | segment _TEXT public align=1 class=CODE use32 39 | global _asm_main 40 | extern get_int, print_sum 41 | _asm_main: 42 | enter 0,0 ; setup routine 43 | pusha 44 | 45 | mov edx, 1 ; edx is 'i' in pseudo-code 46 | while_loop: 47 | push edx ; save i on stack 48 | push dword input ; push address on input on stack 49 | call get_int 50 | add esp, 8 ; remove i and &input from stack 51 | 52 | mov eax, [input] 53 | cmp eax, 0 54 | je end_while 55 | 56 | add [sum], eax ; sum += input 57 | 58 | inc edx 59 | jmp short while_loop 60 | 61 | end_while: 62 | push dword [sum] ; push value of sum onto stack 63 | call print_sum 64 | pop ecx ; remove [sum] from stack 65 | 66 | popa 67 | leave 68 | ret 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /examples/borland/main5.c: -------------------------------------------------------------------------------- 1 | /* 2 | * file: main5.c 3 | * main C program that uses assembly routine in sub5.asm 4 | * to create executable: 5 | * DJGPP: gcc -o sub5 main5.c sub5.o asm_io.o 6 | * Borland: bcc32 sub5.obj main5.c asm_io.obj 7 | */ 8 | 9 | #include 10 | 11 | #include "cdecl.h" 12 | 13 | void PRE_CDECL calc_sum( int, int * ) POST_CDECL; /* prototype for assembly routine */ 14 | 15 | int main( void ) 16 | { 17 | int n, sum; 18 | 19 | printf("Sum integers up to: "); 20 | scanf("%d", &n); 21 | calc_sum(n, &sum); 22 | printf("Sum is %d\n", sum); 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /examples/borland/main6.c: -------------------------------------------------------------------------------- 1 | /* 2 | * file: main6.c 3 | * main C program that uses assembly routine in sub5.asm 4 | * to create executable: 5 | * DJGPP: gcc -o sub5 main5.c sub5.o 6 | * Borland: bcc32 sub5.obj main5.c 7 | */ 8 | 9 | #include 10 | 11 | #include "cdecl.h" 12 | 13 | int PRE_CDECL calc_sum( int ) POST_CDECL; /* prototype for assembly routine */ 14 | 15 | int main( void ) 16 | { 17 | int n, sum; 18 | 19 | printf("Sum integers up to: "); 20 | scanf("%d", &n); 21 | sum = calc_sum(n); 22 | printf("Sum is %d\n", sum); 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /examples/borland/math.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: math.asm 5 | ; This program demonstrates how the integer multiplication and division 6 | ; instructions work. 7 | ; 8 | ; To create executable: 9 | ; nasm -f coff math.asm 10 | ; gcc -o math math.o driver.c asm_io.o 11 | 12 | %include "asm_io.inc" 13 | 14 | segment _DATA public align=4 class=DATA use32 15 | ; 16 | ; Output strings 17 | ; 18 | prompt db "Enter a number: ", 0 19 | square_msg db "Square of input is ", 0 20 | cube_msg db "Cube of input is ", 0 21 | cube25_msg db "Cube of input times 25 is ", 0 22 | quot_msg db "Quotient of cube/100 is ", 0 23 | rem_msg db "Remainder of cube/100 is ", 0 24 | neg_msg db "The negation of the remainder is ", 0 25 | 26 | segment _BSS public align=4 class=BSS use32 27 | input resd 1 28 | 29 | 30 | segment _TEXT public align=1 class=CODE use32 31 | global _asm_main 32 | _asm_main: 33 | enter 0,0 ; setup routine 34 | pusha 35 | 36 | mov eax, prompt 37 | call print_string 38 | 39 | call read_int 40 | mov [input], eax 41 | 42 | imul eax ; edx:eax = eax * eax 43 | mov ebx, eax ; save answer in ebx 44 | mov eax, square_msg 45 | call print_string 46 | mov eax, ebx 47 | call print_int 48 | call print_nl 49 | 50 | mov ebx, eax 51 | imul ebx, [input] ; ebx *= [input] 52 | mov eax, cube_msg 53 | call print_string 54 | mov eax, ebx 55 | call print_int 56 | call print_nl 57 | 58 | imul ecx, ebx, 25 ; ecx = ebx*25 59 | mov eax, cube25_msg 60 | call print_string 61 | mov eax, ecx 62 | call print_int 63 | call print_nl 64 | 65 | mov eax, ebx 66 | cdq ; initialize edx by sign extension 67 | mov ecx, 100 ; can't divide by immediate value 68 | idiv ecx ; edx:eax / ecx 69 | mov ecx, eax ; save quotient into ecx 70 | mov eax, quot_msg 71 | call print_string 72 | mov eax, ecx 73 | call print_int 74 | call print_nl 75 | mov eax, rem_msg 76 | call print_string 77 | mov eax, edx 78 | call print_int 79 | call print_nl 80 | 81 | neg edx ; negate the remainder 82 | mov eax, neg_msg 83 | call print_string 84 | mov eax, edx 85 | call print_int 86 | call print_nl 87 | 88 | popa 89 | mov eax, 0 ; return back to C 90 | leave 91 | ret 92 | 93 | 94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /examples/borland/max.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: max.asm 5 | ; This example demostrates how to avoid conditional branches 6 | 7 | %include "asm_io.inc" 8 | segment _DATA public align=4 class=DATA use32 9 | 10 | message1 db "Enter a number: ",0 11 | message2 db "Enter another number: ", 0 12 | message3 db "The larger number is: ", 0 13 | 14 | segment _BSS public align=4 class=BSS use32 15 | 16 | input1 resd 1 ; first number entered 17 | 18 | group DGROUP _BSS _DATA 19 | 20 | segment _TEXT public align=1 class=CODE use32 21 | global _asm_main 22 | _asm_main: 23 | enter 0,0 ; setup routine 24 | pusha 25 | 26 | mov eax, message1 ; print out first message 27 | call print_string 28 | call read_int ; input first number 29 | mov [input1], eax 30 | 31 | mov eax, message2 ; print out second message 32 | call print_string 33 | call read_int ; input second number (in eax) 34 | 35 | xor ebx, ebx ; ebx = 0 36 | cmp eax, [input1] ; compare second and first number 37 | setg bl ; ebx = (input2 > input1) ? 1 : 0 38 | neg ebx ; ebx = (input2 > input1) ? 0xFFFFFFFF : 0 39 | mov ecx, ebx ; ecx = (input2 > input1) ? 0xFFFFFFFF : 0 40 | and ecx, eax ; ecx = (input2 > input1) ? input2 : 0 41 | not ebx ; ebx = (input2 > input1) ? 0 : 0xFFFFFFFF 42 | and ebx, [input1] ; ebx = (input2 > input1) ? 0 : input1 43 | or ecx, ebx ; ecx = (input2 > input1) ? input2 : input1 44 | 45 | mov eax, message3 ; print out result 46 | call print_string 47 | mov eax, ecx 48 | call print_int 49 | call print_nl 50 | 51 | popa 52 | mov eax, 0 ; return back to C 53 | leave 54 | ret 55 | 56 | 57 | -------------------------------------------------------------------------------- /examples/borland/memex.c: -------------------------------------------------------------------------------- 1 | /* 2 | * file: memex.c 3 | */ 4 | 5 | #include 6 | 7 | #include "cdecl.h" 8 | 9 | #define STR_SIZE 30 10 | /* 11 | * prototypes 12 | */ 13 | 14 | void PRE_CDECL asm_copy( void *, 15 | const void *, 16 | unsigned ) POST_CDECL; 17 | 18 | void * PRE_CDECL asm_find( const void *, 19 | char target, 20 | unsigned ) POST_CDECL; 21 | 22 | unsigned PRE_CDECL asm_strlen( const char * ) POST_CDECL; 23 | 24 | void PRE_CDECL asm_strcpy( char *, 25 | const char * ) POST_CDECL; 26 | 27 | int main() 28 | { 29 | char st1[STR_SIZE] = "test string"; 30 | char st2[STR_SIZE]; 31 | char * st; 32 | char ch; 33 | 34 | asm_copy(st2, st1, STR_SIZE); /* copy all 30 chars of string */ 35 | printf("%s\n", st2); 36 | 37 | printf("Enter a char: "); /* look for byte in string */ 38 | scanf("%c%*[^\n]", &ch); 39 | st = asm_find(st2, ch, STR_SIZE); 40 | if ( st ) 41 | printf("Found it: %s\n", st); 42 | else 43 | printf("Not found\n"); 44 | 45 | st1[0] = 0; 46 | printf("Enter string:"); 47 | scanf("%s", st1); 48 | printf("len = %u\n", asm_strlen(st1)); 49 | 50 | asm_strcpy( st2, st1); /* copy meaningful data in string */ 51 | printf("%s\n", st2 ); 52 | 53 | return 0; 54 | } 55 | 56 | -------------------------------------------------------------------------------- /examples/borland/quadt.c: -------------------------------------------------------------------------------- 1 | /* 2 | * file: quadt.c 3 | * Test file for quad.asm 4 | */ 5 | 6 | #include 7 | 8 | #include "cdecl.h" 9 | 10 | int PRE_CDECL quadratic( double, double, double, double *, double *) POST_CDECL; 11 | 12 | int main() 13 | { 14 | double a,b,c, root1, root2; 15 | 16 | printf("Enter a, b, c: "); 17 | scanf("%lf %lf %lf", &a, &b, &c); 18 | if (quadratic( a, b, c, &root1, &root2) ) 19 | printf("roots: %.10g %.10g\n", root1, root2); 20 | else 21 | printf("No real roots\n"); 22 | return 0; 23 | } 24 | 25 | -------------------------------------------------------------------------------- /examples/borland/read.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: read.asm 5 | ; This subroutine reads an array of doubles from a file 6 | 7 | segment _DATA public align=4 class=DATA use32 8 | format db "%lf", 0 ; format for fscanf() 9 | 10 | segment _BSS public align=4 class=BSS use32 11 | 12 | group DGROUP _BSS _DATA 13 | 14 | segment _TEXT public align=1 class=CODE use32 15 | global _read_doubles 16 | extern _fscanf 17 | 18 | %define SIZEOF_DOUBLE 8 19 | %define FP dword [ebp + 8] 20 | %define ARRAYP dword [ebp + 12] 21 | %define ARRAY_SIZE dword [ebp + 16] 22 | %define TEMP_DOUBLE [ebp - 8] 23 | 24 | ; 25 | ; function _read_doubles 26 | ; C prototype: 27 | ; int read_doubles( FILE * fp, double * arrayp, int array_size ); 28 | ; This function reads doubles from a text file into an array, until 29 | ; EOF or array is full. 30 | ; Parameters: 31 | ; fp - FILE pointer to read from (must be open for input) 32 | ; arrayp - pointer to double array to read into 33 | ; array_size - number of elements in array 34 | ; Return value: 35 | ; number of doubles stored into array (in EAX) 36 | 37 | _read_doubles: 38 | push ebp 39 | mov ebp,esp 40 | sub esp, SIZEOF_DOUBLE ; define one double on stack 41 | 42 | push esi ; save esi 43 | mov esi, ARRAYP ; esi = ARRAYP 44 | xor edx, edx ; edx = array index (initially 0) 45 | 46 | while_loop: 47 | cmp edx, ARRAY_SIZE ; is edx < ARRAY_SIZE? 48 | jnl short quit ; if not, quit loop 49 | ; 50 | ; call fscanf() to read a double into TEMP_DOUBLE 51 | ; fscanf() might change edx so save it 52 | ; 53 | push edx ; save edx 54 | lea eax, TEMP_DOUBLE 55 | push eax ; push &TEMP_DOUBLE 56 | push dword format ; push &format 57 | push FP ; push file pointer 58 | call _fscanf 59 | add esp, 12 60 | pop edx ; restore edx 61 | cmp eax, 1 ; did fscanf return 1? 62 | jne short quit ; if not, quit loop 63 | 64 | ; 65 | ; copy TEMP_DOUBLE into ARRAYP[edx] 66 | ; (The 8-bytes of the double are copied by two 4-byte copies) 67 | ; 68 | mov eax, [ebp - 8] 69 | mov [esi + 8*edx], eax ; first copy lowest 4 bytes 70 | mov eax, [ebp - 4] 71 | mov [esi + 8*edx + 4], eax ; next copy highest 4 bytes 72 | 73 | inc edx 74 | jmp while_loop 75 | 76 | quit: 77 | pop esi ; restore esi 78 | 79 | mov eax, edx ; store return value into eax 80 | 81 | mov esp, ebp 82 | pop ebp 83 | ret 84 | 85 | -------------------------------------------------------------------------------- /examples/borland/readt.c: -------------------------------------------------------------------------------- 1 | /* 2 | * file: readt.c 3 | * This program tests the 32-bit read_doubles() assembly procedure. 4 | * It reads the doubles from stdin. 5 | * (Use redirection to read from file.) 6 | */ 7 | 8 | #include 9 | 10 | #include "cdecl.h" 11 | 12 | extern int PRE_CDECL read_doubles( FILE *, double *, int ) POST_CDECL; 13 | 14 | #define MAX 100 15 | 16 | int main() 17 | { 18 | int i,n; 19 | double a[MAX]; 20 | 21 | n = read_doubles(stdin, a, MAX); 22 | 23 | for( i=0; i < n; i++ ) 24 | printf("%3d %g\n", i, a[i]); 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /examples/borland/skel.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: skel.asm 5 | ; This file is a skeleton that can be used to start assembly programs. 6 | 7 | %include "asm_io.inc" 8 | segment _DATA public align=4 class=DATA use32 9 | ; 10 | ; initialized data is put in the data segment here 11 | ; 12 | 13 | 14 | segment _BSS public align=4 class=BSS use32 15 | ; 16 | ; uninitialized data is put in the bss segment 17 | ; 18 | 19 | 20 | group DGROUP _BSS _DATA 21 | 22 | segment _TEXT public align=1 class=CODE use32 23 | global _asm_main 24 | _asm_main: 25 | enter 0,0 ; setup routine 26 | pusha 27 | 28 | ; 29 | ; code is put in the text segment. Do not modify the code before 30 | ; or after this comment. 31 | ; 32 | 33 | popa 34 | mov eax, 0 ; return back to C 35 | leave 36 | ret 37 | 38 | 39 | -------------------------------------------------------------------------------- /examples/borland/sub1.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: sub1.asm 5 | ; Subprogram example program 6 | ; 7 | ; To create executable: 8 | ; Using djgpp: 9 | ; nasm -f coff sub1.asm 10 | ; gcc -o sub1 sub1.o driver.c asm_io.o 11 | ; 12 | 13 | %include "asm_io.inc" 14 | 15 | segment _DATA public align=4 class=DATA use32 16 | prompt1 db "Enter a number: ", 0 ; don't forget nul terminator 17 | prompt2 db "Enter another number: ", 0 18 | outmsg1 db "You entered ", 0 19 | outmsg2 db " and ", 0 20 | outmsg3 db ", the sum of these is ", 0 21 | 22 | segment _BSS public align=4 class=BSS use32 23 | ; 24 | ; These labels refer to double words used to store the inputs 25 | ; 26 | input1 resd 1 27 | input2 resd 1 28 | 29 | group DGROUP _BSS _DATA 30 | 31 | segment _TEXT public align=1 class=CODE use32 32 | global _asm_main 33 | _asm_main: 34 | enter 0,0 ; setup routine 35 | pusha 36 | 37 | mov eax, prompt1 ; print out prompt 38 | call print_string 39 | 40 | mov ebx, input1 ; store address of input1 into ebx 41 | mov ecx, ret1 ; store return address into ecx 42 | jmp short get_int ; read integer 43 | ret1: 44 | mov eax, prompt2 ; print out prompt 45 | call print_string 46 | 47 | mov ebx, input2 48 | mov ecx, $ + 7 ; ecx = this address + 7 49 | jmp short get_int 50 | 51 | mov eax, [input1] ; eax = dword at input1 52 | add eax, [input2] ; eax += dword at input2 53 | mov ebx, eax ; ebx = eax 54 | ; 55 | ; next print out result message as series of steps 56 | ; 57 | 58 | mov eax, outmsg1 59 | call print_string ; print out first message 60 | mov eax, [input1] 61 | call print_int ; print out input1 62 | mov eax, outmsg2 63 | call print_string ; print out second message 64 | mov eax, [input2] 65 | call print_int ; print out input2 66 | mov eax, outmsg3 67 | call print_string ; print out third message 68 | mov eax, ebx 69 | call print_int ; print out sum (ebx) 70 | call print_nl ; print new-line 71 | 72 | popa 73 | mov eax, 0 ; return back to C 74 | leave 75 | ret 76 | ; 77 | ; subprogram get_int 78 | ; Parameters: 79 | ; ebx - address of dword to store integer into 80 | ; ecx - address of instruction to return to 81 | ; Notes: 82 | ; value of eax is destroyed 83 | get_int: 84 | call read_int 85 | mov [ebx], eax ; store input into memory 86 | jmp ecx ; jump back to caller 87 | 88 | 89 | -------------------------------------------------------------------------------- /examples/borland/sub2.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: sub2.asm 5 | ; Subprogram example program 6 | ; 7 | ; To create executable: 8 | ; Using djgpp: 9 | ; nasm -f coff sub2.asm 10 | ; gcc -o sub1 sub2.o driver.c asm_io.o 11 | ; 12 | ; Using Borland C/C++ 13 | ; nasm -f obj sub2.asm 14 | ; bcc32 sub2.obj driver.c asm_io.obj 15 | 16 | %include "asm_io.inc" 17 | 18 | segment _DATA public align=4 class=DATA use32 19 | prompt1 db "Enter a number: ", 0 ; don't forget nul terminator 20 | prompt2 db "Enter another number: ", 0 21 | outmsg1 db "You entered ", 0 22 | outmsg2 db " and ", 0 23 | outmsg3 db ", the sum of these is ", 0 24 | 25 | segment _BSS public align=4 class=BSS use32 26 | ; 27 | ; These labels refer to double words used to store the inputs 28 | ; 29 | input1 resd 1 30 | input2 resd 1 31 | 32 | group DGROUP _BSS _DATA 33 | 34 | segment _TEXT public align=1 class=CODE use32 35 | global _asm_main 36 | _asm_main: 37 | enter 0,0 ; setup routine 38 | pusha 39 | 40 | mov eax, prompt1 ; print out prompt 41 | call print_string 42 | 43 | mov ebx, input1 ; store address of input1 into ebx 44 | call get_int ; read integer 45 | 46 | mov eax, prompt2 ; print out prompt 47 | call print_string 48 | 49 | mov ebx, input2 50 | call get_int 51 | 52 | mov eax, [input1] ; eax = dword at input1 53 | add eax, [input2] ; eax += dword at input2 54 | mov ebx, eax ; ebx = eax 55 | ; 56 | ; next print out result message as series of steps 57 | ; 58 | 59 | mov eax, outmsg1 60 | call print_string ; print out first message 61 | mov eax, [input1] 62 | call print_int ; print out input1 63 | mov eax, outmsg2 64 | call print_string ; print out second message 65 | mov eax, [input2] 66 | call print_int ; print out input2 67 | mov eax, outmsg3 68 | call print_string ; print out third message 69 | mov eax, ebx 70 | call print_int ; print out sum (ebx) 71 | call print_nl ; print new-line 72 | 73 | popa 74 | mov eax, 0 ; return back to C 75 | leave 76 | ret 77 | ; 78 | ; subprogram get_int 79 | ; Parameters: 80 | ; ebx - address of word to store integer into 81 | ; Notes: 82 | ; value of eax is destroyed 83 | get_int: 84 | call read_int 85 | mov [ebx], eax ; store input into memory 86 | ret ; jump back to caller 87 | 88 | 89 | -------------------------------------------------------------------------------- /examples/borland/sub4.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: sub4.asm 5 | ; Subprogram example 6 | 7 | %include "asm_io.inc" 8 | 9 | ; 10 | ; subprogram get_int 11 | ; Parameters (in order pushed on stack) 12 | ; number of input (at [ebp + 12]) 13 | ; address of word to store input into (at [ebp + 8]) 14 | ; Notes: 15 | ; values of eax and ebx are destroyed 16 | segment _DATA public align=4 class=DATA use32 17 | prompt db ") Enter an integer number (0 to quit): ", 0 18 | 19 | segment _BSS public align=4 class=BSS use32 20 | 21 | group DGROUP _BSS _DATA 22 | 23 | segment _TEXT public align=1 class=CODE use32 24 | global get_int, print_sum 25 | get_int: 26 | enter 0,0 27 | 28 | mov eax, [ebp + 12] 29 | call print_int 30 | 31 | mov eax, prompt 32 | call print_string 33 | 34 | call read_int 35 | mov ebx, [ebp + 8] 36 | mov [ebx], eax ; store input into memory 37 | 38 | leave 39 | ret ; jump back to caller 40 | 41 | ; subprogram print_sum 42 | ; prints out the sum 43 | ; Parameter: 44 | ; sum to print out (at [ebp+8]) 45 | ; Note: destroys value of eax 46 | ; 47 | segment _DATA 48 | result db "The sum is ", 0 49 | 50 | segment _TEXT 51 | print_sum: 52 | enter 0,0 53 | 54 | mov eax, result 55 | call print_string 56 | 57 | mov eax, [ebp+8] 58 | call print_int 59 | call print_nl 60 | 61 | leave 62 | ret 63 | 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /examples/borland/sub5.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: sub5.asm 5 | ; Subprogram to C interfacing example 6 | 7 | %include "asm_io.inc" 8 | 9 | ; subroutine _calc_sum 10 | ; finds the sum of the integers 1 through n 11 | ; Parameters: 12 | ; n - what to sum up to (at [ebp + 8]) 13 | ; sump - pointer to int to store sum into (at [ebp + 12]) 14 | ; pseudo C code: 15 | ; void calc_sum( int n, int * sump ) 16 | ; { 17 | ; int i, sum = 0; 18 | ; for( i=1; i <= n; i++ ) 19 | ; sum += i; 20 | ; *sump = sum; 21 | ; } 22 | ; 23 | ; To assemble: 24 | ; DJGPP: nasm -f coff sub5.asm 25 | ; Borland: nasm -f obj sub5.asm 26 | 27 | segment _TEXT public align=1 class=CODE use32 28 | global _calc_sum 29 | ; 30 | ; local variable: 31 | ; sum at [ebp-4] 32 | _calc_sum: 33 | enter 4,0 ; allocate room for sum on stack 34 | push ebx ; IMPORTANT! 35 | 36 | mov dword [ebp-4],0 ; sum = 0 37 | dump_stack 1, 2, 4 ; print out stack from ebp-8 to ebp+16 38 | mov ecx, 1 ; ecx is i in pseudocode 39 | for_loop: 40 | cmp ecx, [ebp+8] ; cmp i and n 41 | jnle end_for ; if not i <= n, quit 42 | 43 | add [ebp-4], ecx ; sum += i 44 | inc ecx 45 | jmp short for_loop 46 | 47 | end_for: 48 | mov ebx, [ebp+12] ; ebx = sump 49 | mov eax, [ebp-4] ; eax = sum 50 | mov [ebx], eax 51 | 52 | pop ebx ; restore ebx 53 | leave 54 | ret 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /examples/borland/sub6.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: sub6.asm 5 | ; Subprogram to C interfacing example 6 | 7 | ; subroutine _calc_sum 8 | ; finds the sum of the integers 1 through n 9 | ; Parameters: 10 | ; n - what to sum up to (at [ebp + 8]) 11 | ; Return value: 12 | ; value of sum 13 | ; pseudo C code: 14 | ; int calc_sum( int n ) 15 | ; { 16 | ; int i, sum = 0; 17 | ; for( i=1; i <= n; i++ ) 18 | ; sum += i; 19 | ; return sum; 20 | ; } 21 | ; 22 | ; To assemble: 23 | ; DJGPP: nasm -f coff sub6.asm 24 | ; Borland: nasm -f obj sub6.asm 25 | 26 | segment _TEXT public align=1 class=CODE use32 27 | global _calc_sum 28 | ; 29 | ; local variable: 30 | ; sum at [ebp-4] 31 | _calc_sum: 32 | enter 4,0 ; make room for sum on stack 33 | 34 | mov dword [ebp-4],0 ; sum = 0 35 | mov ecx, 1 ; ecx is i in pseudocode 36 | for_loop: 37 | cmp ecx, [ebp+8] ; cmp i and n 38 | jnle end_for ; if not i <= n, quit 39 | 40 | add [ebp-4], ecx ; sum += i 41 | inc ecx 42 | jmp short for_loop 43 | 44 | end_for: 45 | mov eax, [ebp-4] ; eax = sum 46 | 47 | leave 48 | ret 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /examples/borland/test_big_int.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * file: big_int_test.cpp 3 | * A small test program for the Big_int class 4 | */ 5 | #include "big_int.hpp" 6 | #include 7 | 8 | // Borland (or at least bcc32 ver 5.2) doesn't support the std namespace 9 | #if ! ( ( defined(__BORLANDC__) && __BORLANDC__ < 0x550 ) || defined(__WATCOMC__) ) 10 | using namespace std; 11 | #endif 12 | 13 | int main() 14 | { 15 | try { 16 | // 12345678901234567890 17 | Big_int b(5,"8000000000000a00b"); 18 | Big_int a(5,"80000000000010230"); 19 | Big_int c = a + b; 20 | cout << a << " + " << b << " = " << c << endl; 21 | for( int i=0; i < 2; i++ ) { 22 | c = c + a; 23 | cout << "c = " << c << endl; 24 | } 25 | cout << "c-1 = " << c - Big_int(5,1) << endl; 26 | Big_int d(5, "12345678"); 27 | cout << "d = " << d << endl; 28 | cout << "c == d " << (c == d) << endl; 29 | cout << "c > d " << (c > d) << endl; 30 | } 31 | catch( const char * str ) { 32 | cerr << "Caught: " << str << endl; 33 | } 34 | catch( Big_int::Overflow ) { 35 | cerr << "Overflow" << endl; 36 | } 37 | catch( Big_int::Size_mismatch ) { 38 | cerr << "Size mismatch" << endl; 39 | } 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /examples/cygwin-ex.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/humanshell/assembly/474346d24ed2e2abb0e4edd9dc085e6b84104001/examples/cygwin-ex.zip -------------------------------------------------------------------------------- /examples/cygwin/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # cygwin makefile 3 | # Use with make 4 | # 5 | 6 | .SUFFIXES: 7 | .SUFFIXES: .o .asm .cpp .c 8 | 9 | AS=nasm 10 | ASFLAGS= -f win32 11 | CFLAGS= 12 | CC=gcc 13 | CXX=g++ 14 | CXXFLAGS= 15 | 16 | .asm.o: 17 | $(AS) $(ASFLAGS) -o $*.o $*.asm 18 | 19 | .cpp.o: 20 | $(CXX) -c $(CXXFLAGS) $*.cpp 21 | 22 | .c.o: 23 | $(CC) -c $(CFLAGS) $*.c 24 | 25 | all: prime math sub1 sub2 sub3 sub4 sub5 sub6 first memex dmaxt asm_io.o fprime quadt test_big_int 26 | 27 | prime: driver.o prime.o asm_io.o 28 | $(CC) $(CFLAGS) -oprime driver.o prime.o asm_io.o 29 | 30 | math : driver.o math.o asm_io.o 31 | $(CC) $(CFLAGS) -omath driver.o math.o asm_io.o 32 | 33 | first : driver.o first.o asm_io.o 34 | $(CC) $(CFLAGS) -ofirst driver.o first.o asm_io.o 35 | 36 | sub1 : driver.o sub1.o asm_io.o 37 | $(CC) $(CFLAGS) -osub1 driver.o sub1.o asm_io.o 38 | 39 | sub2 : driver.o sub2.o asm_io.o 40 | $(CC) $(CFLAGS) -osub2 driver.o sub2.o asm_io.o 41 | 42 | sub3 : driver.o sub3.o asm_io.o 43 | $(CC) $(CFLAGS) -osub3 driver.o sub3.o asm_io.o 44 | 45 | sub4 : driver.o sub4.o main4.o asm_io.o 46 | $(CC) $(CFLAGS) -osub4 driver.o sub4.o main4.o asm_io.o 47 | 48 | sub5 : main5.o sub5.o asm_io.o 49 | $(CC) $(CFLAGS) -osub5 main5.o sub5.o asm_io.o 50 | 51 | sub6 : main6.o sub6.o 52 | $(CC) $(CFLAGS) -osub6 main6.o sub6.o 53 | 54 | asm_io.o : asm_io.asm 55 | $(AS) $(ASFLAGS) -d COFF_TYPE -o asm_io.o asm_io.asm 56 | 57 | array1 : driver.o array1.o array1c.o 58 | $(CC) $(CFLAGS) -oarray1 array1.o array1c.o asm_io.o 59 | 60 | memex : memex.o memory.o 61 | $(CC) $(CFLAGS) -omemex memex.o memory.o 62 | 63 | dmaxt : dmaxt.o dmax.o 64 | $(CC) $(CFLAGS) -odmaxt dmaxt.o dmax.o 65 | 66 | quadt : quadt.o quad.o 67 | $(CC) $(CFLAGS) -oquadt quadt.o quad.o 68 | 69 | readt : readt.o read.o 70 | $(CC) $(CFLAGS) -oreadt readt.o read.o 71 | 72 | fprime : fprime.o prime2.o 73 | $(CC) $(CFLAGS) -ofprime fprime.o prime2.o 74 | 75 | test_big_int : test_big_int.o big_int.o big_math.o 76 | $(CXX) $(CXXFLAGS) -otest_big_int test_big_int.o big_int.o big_math.o 77 | 78 | big_int.o : big_int.hpp 79 | 80 | test_big_int.o : big_int.hpp 81 | 82 | first.o : asm_io.inc first.asm 83 | 84 | sub1.o : asm_io.inc 85 | 86 | sub2.o : asm_io.inc 87 | 88 | sub3.o : asm_io.inc 89 | 90 | sub4.o : asm_io.inc 91 | 92 | main4.o : asm_io.inc 93 | 94 | driver.o : driver.c 95 | 96 | 97 | clean : 98 | rm *.o 99 | -------------------------------------------------------------------------------- /examples/cygwin/array1c.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Driver file for array1.asm file 3 | */ 4 | 5 | #include 6 | 7 | #include "cdecl.h" 8 | 9 | int PRE_CDECL asm_main( void ) POST_CDECL; 10 | void PRE_CDECL dump_line( void ) POST_CDECL; 11 | 12 | int main() 13 | { 14 | int ret_status; 15 | ret_status = asm_main(); 16 | return ret_status; 17 | } 18 | 19 | /* 20 | * function dump_line 21 | * dumps all chars left in current line from input buffer 22 | */ 23 | void dump_line() 24 | { 25 | int ch; 26 | 27 | while( (ch = getchar()) != EOF && ch != '\n') 28 | /* null body*/ ; 29 | } 30 | 31 | -------------------------------------------------------------------------------- /examples/cygwin/asm_io.inc: -------------------------------------------------------------------------------- 1 | extern read_int, print_int, print_string 2 | extern read_char, print_char, print_nl 3 | extern sub_dump_regs, sub_dump_mem, sub_dump_math, sub_dump_stack 4 | 5 | %macro dump_regs 1 6 | push dword %1 7 | call sub_dump_regs 8 | %endmacro 9 | 10 | 11 | ; 12 | ; usage: dump_mem label, start-address, # paragraphs 13 | %macro dump_mem 3 14 | push dword %1 15 | push dword %2 16 | push dword %3 17 | call sub_dump_mem 18 | %endmacro 19 | 20 | %macro dump_math 1 21 | push dword %1 22 | call sub_dump_math 23 | %endmacro 24 | 25 | %macro dump_stack 3 26 | push dword %3 27 | push dword %2 28 | push dword %1 29 | call sub_dump_stack 30 | %endmacro -------------------------------------------------------------------------------- /examples/cygwin/asm_io.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/humanshell/assembly/474346d24ed2e2abb0e4edd9dc085e6b84104001/examples/cygwin/asm_io.o -------------------------------------------------------------------------------- /examples/cygwin/bitcount.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* 4 | * function bit_count 5 | * Counts the number of bits on (i.e., = 1) in an unsigned int 6 | * (This code assumes that an int is 32-bits!) 7 | * Parameter: 8 | * x - number to count bits of 9 | * Return value: 10 | * number of bits on in x 11 | */ 12 | int bit_count(unsigned int x ) 13 | { 14 | static unsigned int mask[] = { 0x55555555, 15 | 0x33333333, 16 | 0x0F0F0F0F, 17 | 0x00FF00FF, 18 | 0x0000FFFF }; 19 | int i; 20 | int shift; /* number of positions to shift to right */ 21 | 22 | for( i=0, shift=1; i < 5; i++, shift *= 2 ) 23 | x = (x & mask[i]) + ( (x >> shift) & mask[i] ); 24 | return x; 25 | } 26 | 27 | 28 | int main() 29 | { 30 | unsigned int x; 31 | 32 | printf("Enter a number: "); 33 | scanf("%i", &x); 34 | printf("There are %d bits on in %X\n", bit_count(x), x); 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /examples/cygwin/bitcount2.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static unsigned char byte_bit_count[256]; /* lookup table */ 4 | 5 | void initialize_count_bits() 6 | { 7 | int cnt, i, data; 8 | 9 | for( i = 0; i < 256; i++ ) { 10 | cnt = 0; 11 | data = i; 12 | while( data != 0 ) { 13 | data = data & (data - 1); 14 | cnt++; 15 | } 16 | byte_bit_count[i] = cnt; 17 | printf("%d %d\n", i, byte_bit_count[i]); 18 | } 19 | } 20 | 21 | int count_bits( unsigned int data ) 22 | { 23 | const unsigned char * dword = ( unsigned char *) & data; 24 | 25 | return byte_bit_count[dword[0]] + byte_bit_count[dword[1]] + 26 | byte_bit_count[dword[2]] + byte_bit_count[dword[3]]; 27 | } 28 | 29 | int main() 30 | { 31 | unsigned int x; 32 | 33 | initialize_count_bits(); 34 | printf("Enter a number: "); 35 | scanf("%i", &x); 36 | printf("There are %d bits on in %X\n", count_bits(x), x); 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /examples/cygwin/cdecl.h: -------------------------------------------------------------------------------- 1 | #ifndef CDECL_HEADER_FILE 2 | #define CDECL_HEADER_FILE 3 | 4 | /* 5 | * Define macros to specify the standard C calling convention 6 | * The macros are designed so that they will work with all 7 | * supported C/C++ compilers. 8 | * 9 | * To use define your function prototype like this: 10 | * 11 | * return_type PRE_CDECL func_name( args ) POST_CDECL; 12 | * 13 | * For example: 14 | * 15 | * int PRE_CDECL f( int x, int y) POST_CDECL; 16 | */ 17 | 18 | 19 | #if defined(__GNUC__) 20 | # define PRE_CDECL 21 | # define POST_CDECL __attribute__((cdecl)) 22 | #else 23 | # define PRE_CDECL __cdecl 24 | # define POST_CDECL 25 | #endif 26 | 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /examples/cygwin/dmax.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: dmax.asm 5 | 6 | global _dmax 7 | 8 | 9 | 10 | segment .text 11 | ; function _dmax 12 | ; returns the larger of its two double arguments 13 | ; C prototype 14 | ; double dmax( double d1, double d2 ) 15 | ; Parameters: 16 | ; d1 - first double 17 | ; d2 - second double 18 | ; Return value: 19 | ; larger of d1 and d2 (in ST0) 20 | 21 | ; next, some helpful symbols are defined 22 | 23 | %define d1 [ebp+8] 24 | %define d2 [ebp+16] 25 | 26 | _dmax: 27 | enter 0, 0 28 | 29 | fld qword d2 30 | fld qword d1 ; ST0 = d1, ST1 = d2 31 | fcomip st1 ; ST0 = d2 32 | jna short d2_bigger 33 | fcomp st0 ; pop d2 from stack 34 | fld qword d1 ; ST0 = d1 35 | 36 | d2_bigger: ; if d2 is bigger, nothing to do 37 | 38 | exit: 39 | leave 40 | ret 41 | 42 | 43 | -------------------------------------------------------------------------------- /examples/cygwin/dmaxt.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "cdecl.h" 4 | 5 | double PRE_CDECL dmax( double, double ) POST_CDECL; 6 | 7 | int main() 8 | { 9 | double d1, d2; 10 | 11 | printf("Enter two doubles: "); 12 | scanf("%lf %lf", &d1, &d2); 13 | 14 | printf("The larger of %g and %g is %g\n", d1, d2, dmax(d1,d2)); 15 | return 0; 16 | } 17 | 18 | -------------------------------------------------------------------------------- /examples/cygwin/driver.c: -------------------------------------------------------------------------------- 1 | #include "cdecl.h" 2 | 3 | int PRE_CDECL asm_main( void ) POST_CDECL; 4 | 5 | int main() 6 | { 7 | int ret_status; 8 | ret_status = asm_main(); 9 | return ret_status; 10 | } 11 | -------------------------------------------------------------------------------- /examples/cygwin/fprime.c: -------------------------------------------------------------------------------- 1 | /* 2 | * file: fprime.c 3 | * This program calculates prime numbers 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | #include "cdecl.h" 10 | 11 | /* 12 | * function find_primes 13 | * finds the indicated number of primes 14 | * Parameters: 15 | * a - array to hold primes 16 | * n - how many primes to find 17 | */ 18 | extern void PRE_CDECL find_primes( int * a, unsigned n ) POST_CDECL; 19 | 20 | int main() 21 | { 22 | int status; 23 | unsigned i; 24 | unsigned max; 25 | int * a; 26 | 27 | printf("How many primes do you wish to find? "); 28 | scanf("%u", &max); 29 | 30 | a = calloc( sizeof(int), max); 31 | 32 | if ( a ) { 33 | 34 | find_primes(a,max); 35 | 36 | /* 37 | * print out the last 20 primes found 38 | */ 39 | for(i= ( max > 20 ) ? max - 20 : 0; i < max; i++ ) 40 | printf("%3d %d\n", i+1, a[i]); 41 | 42 | free(a); 43 | status = 0; 44 | } 45 | else { 46 | fprintf(stderr, "Can not create array of %u ints\n", max); 47 | status = 1; 48 | } 49 | 50 | return status; 51 | } 52 | -------------------------------------------------------------------------------- /examples/cygwin/main4.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: main4.asm 5 | ; Multi-module subprogram example program 6 | ; 7 | ; To create executable: 8 | ; Using djgpp: 9 | ; nasm -f coff sub4.asm 10 | ; nasm -f coff main4.asm 11 | ; gcc -o sub4 sub4.o main4.o driver.c asm_io.o 12 | ; 13 | ; Using Borland C/C++ 14 | ; nasm -f obj sub4.asm 15 | ; nasm -f obj main4.asm 16 | ; bcc32 sub4.obj main4.asm driver.c asm_io.obj 17 | 18 | %include "asm_io.inc" 19 | 20 | segment .data 21 | sum dd 0 22 | 23 | segment .bss 24 | input resd 1 25 | 26 | 27 | 28 | ; 29 | ; psuedo-code algorithm 30 | ; i = 1; 31 | ; sum = 0; 32 | ; while( get_int(i, &input), input != 0 ) { 33 | ; sum += input; 34 | ; i++; 35 | ; } 36 | ; print_sum(num); 37 | 38 | segment .text 39 | global _asm_main 40 | extern get_int, print_sum 41 | _asm_main: 42 | enter 0,0 ; setup routine 43 | pusha 44 | 45 | mov edx, 1 ; edx is 'i' in pseudo-code 46 | while_loop: 47 | push edx ; save i on stack 48 | push dword input ; push address on input on stack 49 | call get_int 50 | add esp, 8 ; remove i and &input from stack 51 | 52 | mov eax, [input] 53 | cmp eax, 0 54 | je end_while 55 | 56 | add [sum], eax ; sum += input 57 | 58 | inc edx 59 | jmp short while_loop 60 | 61 | end_while: 62 | push dword [sum] ; push value of sum onto stack 63 | call print_sum 64 | pop ecx ; remove [sum] from stack 65 | 66 | popa 67 | leave 68 | ret 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /examples/cygwin/main5.c: -------------------------------------------------------------------------------- 1 | /* 2 | * file: main5.c 3 | * main C program that uses assembly routine in sub5.asm 4 | * to create executable: 5 | * DJGPP: gcc -o sub5 main5.c sub5.o asm_io.o 6 | * Borland: bcc32 sub5.obj main5.c asm_io.obj 7 | */ 8 | 9 | #include 10 | 11 | #include "cdecl.h" 12 | 13 | void PRE_CDECL calc_sum( int, int * ) POST_CDECL; /* prototype for assembly routine */ 14 | 15 | int main( void ) 16 | { 17 | int n, sum; 18 | 19 | printf("Sum integers up to: "); 20 | scanf("%d", &n); 21 | calc_sum(n, &sum); 22 | printf("Sum is %d\n", sum); 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /examples/cygwin/main6.c: -------------------------------------------------------------------------------- 1 | /* 2 | * file: main6.c 3 | * main C program that uses assembly routine in sub5.asm 4 | * to create executable: 5 | * DJGPP: gcc -o sub5 main5.c sub5.o 6 | * Borland: bcc32 sub5.obj main5.c 7 | */ 8 | 9 | #include 10 | 11 | #include "cdecl.h" 12 | 13 | int PRE_CDECL calc_sum( int ) POST_CDECL; /* prototype for assembly routine */ 14 | 15 | int main( void ) 16 | { 17 | int n, sum; 18 | 19 | printf("Sum integers up to: "); 20 | scanf("%d", &n); 21 | sum = calc_sum(n); 22 | printf("Sum is %d\n", sum); 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /examples/cygwin/math.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: math.asm 5 | ; This program demonstrates how the integer multiplication and division 6 | ; instructions work. 7 | ; 8 | ; To create executable: 9 | ; nasm -f coff math.asm 10 | ; gcc -o math math.o driver.c asm_io.o 11 | 12 | %include "asm_io.inc" 13 | 14 | segment .data 15 | ; 16 | ; Output strings 17 | ; 18 | prompt db "Enter a number: ", 0 19 | square_msg db "Square of input is ", 0 20 | cube_msg db "Cube of input is ", 0 21 | cube25_msg db "Cube of input times 25 is ", 0 22 | quot_msg db "Quotient of cube/100 is ", 0 23 | rem_msg db "Remainder of cube/100 is ", 0 24 | neg_msg db "The negation of the remainder is ", 0 25 | 26 | segment .bss 27 | input resd 1 28 | 29 | 30 | segment .text 31 | global _asm_main 32 | _asm_main: 33 | enter 0,0 ; setup routine 34 | pusha 35 | 36 | mov eax, prompt 37 | call print_string 38 | 39 | call read_int 40 | mov [input], eax 41 | 42 | imul eax ; edx:eax = eax * eax 43 | mov ebx, eax ; save answer in ebx 44 | mov eax, square_msg 45 | call print_string 46 | mov eax, ebx 47 | call print_int 48 | call print_nl 49 | 50 | mov ebx, eax 51 | imul ebx, [input] ; ebx *= [input] 52 | mov eax, cube_msg 53 | call print_string 54 | mov eax, ebx 55 | call print_int 56 | call print_nl 57 | 58 | imul ecx, ebx, 25 ; ecx = ebx*25 59 | mov eax, cube25_msg 60 | call print_string 61 | mov eax, ecx 62 | call print_int 63 | call print_nl 64 | 65 | mov eax, ebx 66 | cdq ; initialize edx by sign extension 67 | mov ecx, 100 ; can't divide by immediate value 68 | idiv ecx ; edx:eax / ecx 69 | mov ecx, eax ; save quotient into ecx 70 | mov eax, quot_msg 71 | call print_string 72 | mov eax, ecx 73 | call print_int 74 | call print_nl 75 | mov eax, rem_msg 76 | call print_string 77 | mov eax, edx 78 | call print_int 79 | call print_nl 80 | 81 | neg edx ; negate the remainder 82 | mov eax, neg_msg 83 | call print_string 84 | mov eax, edx 85 | call print_int 86 | call print_nl 87 | 88 | popa 89 | mov eax, 0 ; return back to C 90 | leave 91 | ret 92 | 93 | 94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /examples/cygwin/max.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: max.asm 5 | ; This example demostrates how to avoid conditional branches 6 | 7 | %include "asm_io.inc" 8 | segment .data 9 | 10 | message1 db "Enter a number: ",0 11 | message2 db "Enter another number: ", 0 12 | message3 db "The larger number is: ", 0 13 | 14 | segment .bss 15 | 16 | input1 resd 1 ; first number entered 17 | 18 | 19 | 20 | segment .text 21 | global _asm_main 22 | _asm_main: 23 | enter 0,0 ; setup routine 24 | pusha 25 | 26 | mov eax, message1 ; print out first message 27 | call print_string 28 | call read_int ; input first number 29 | mov [input1], eax 30 | 31 | mov eax, message2 ; print out second message 32 | call print_string 33 | call read_int ; input second number (in eax) 34 | 35 | xor ebx, ebx ; ebx = 0 36 | cmp eax, [input1] ; compare second and first number 37 | setg bl ; ebx = (input2 > input1) ? 1 : 0 38 | neg ebx ; ebx = (input2 > input1) ? 0xFFFFFFFF : 0 39 | mov ecx, ebx ; ecx = (input2 > input1) ? 0xFFFFFFFF : 0 40 | and ecx, eax ; ecx = (input2 > input1) ? input2 : 0 41 | not ebx ; ebx = (input2 > input1) ? 0 : 0xFFFFFFFF 42 | and ebx, [input1] ; ebx = (input2 > input1) ? 0 : input1 43 | or ecx, ebx ; ecx = (input2 > input1) ? input2 : input1 44 | 45 | mov eax, message3 ; print out result 46 | call print_string 47 | mov eax, ecx 48 | call print_int 49 | call print_nl 50 | 51 | popa 52 | mov eax, 0 ; return back to C 53 | leave 54 | ret 55 | 56 | 57 | -------------------------------------------------------------------------------- /examples/cygwin/memex.c: -------------------------------------------------------------------------------- 1 | /* 2 | * file: memex.c 3 | */ 4 | 5 | #include 6 | 7 | #include "cdecl.h" 8 | 9 | #define STR_SIZE 30 10 | /* 11 | * prototypes 12 | */ 13 | 14 | void PRE_CDECL asm_copy( void *, 15 | const void *, 16 | unsigned ) POST_CDECL; 17 | 18 | void * PRE_CDECL asm_find( const void *, 19 | char target, 20 | unsigned ) POST_CDECL; 21 | 22 | unsigned PRE_CDECL asm_strlen( const char * ) POST_CDECL; 23 | 24 | void PRE_CDECL asm_strcpy( char *, 25 | const char * ) POST_CDECL; 26 | 27 | int main() 28 | { 29 | char st1[STR_SIZE] = "test string"; 30 | char st2[STR_SIZE]; 31 | char * st; 32 | char ch; 33 | 34 | asm_copy(st2, st1, STR_SIZE); /* copy all 30 chars of string */ 35 | printf("%s\n", st2); 36 | 37 | printf("Enter a char: "); /* look for byte in string */ 38 | scanf("%c%*[^\n]", &ch); 39 | st = asm_find(st2, ch, STR_SIZE); 40 | if ( st ) 41 | printf("Found it: %s\n", st); 42 | else 43 | printf("Not found\n"); 44 | 45 | st1[0] = 0; 46 | printf("Enter string:"); 47 | scanf("%s", st1); 48 | printf("len = %u\n", asm_strlen(st1)); 49 | 50 | asm_strcpy( st2, st1); /* copy meaningful data in string */ 51 | printf("%s\n", st2 ); 52 | 53 | return 0; 54 | } 55 | 56 | -------------------------------------------------------------------------------- /examples/cygwin/quadt.c: -------------------------------------------------------------------------------- 1 | /* 2 | * file: quadt.c 3 | * Test file for quad.asm 4 | */ 5 | 6 | #include 7 | 8 | #include "cdecl.h" 9 | 10 | int PRE_CDECL quadratic( double, double, double, double *, double *) POST_CDECL; 11 | 12 | int main() 13 | { 14 | double a,b,c, root1, root2; 15 | 16 | printf("Enter a, b, c: "); 17 | scanf("%lf %lf %lf", &a, &b, &c); 18 | if (quadratic( a, b, c, &root1, &root2) ) 19 | printf("roots: %.10g %.10g\n", root1, root2); 20 | else 21 | printf("No real roots\n"); 22 | return 0; 23 | } 24 | 25 | -------------------------------------------------------------------------------- /examples/cygwin/read.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: read.asm 5 | ; This subroutine reads an array of doubles from a file 6 | 7 | segment .data 8 | format db "%lf", 0 ; format for fscanf() 9 | 10 | segment .bss 11 | 12 | 13 | 14 | segment .text 15 | global _read_doubles 16 | extern _fscanf 17 | 18 | %define SIZEOF_DOUBLE 8 19 | %define FP dword [ebp + 8] 20 | %define ARRAYP dword [ebp + 12] 21 | %define ARRAY_SIZE dword [ebp + 16] 22 | %define TEMP_DOUBLE [ebp - 8] 23 | 24 | ; 25 | ; function _read_doubles 26 | ; C prototype: 27 | ; int read_doubles( FILE * fp, double * arrayp, int array_size ); 28 | ; This function reads doubles from a text file into an array, until 29 | ; EOF or array is full. 30 | ; Parameters: 31 | ; fp - FILE pointer to read from (must be open for input) 32 | ; arrayp - pointer to double array to read into 33 | ; array_size - number of elements in array 34 | ; Return value: 35 | ; number of doubles stored into array (in EAX) 36 | 37 | _read_doubles: 38 | push ebp 39 | mov ebp,esp 40 | sub esp, SIZEOF_DOUBLE ; define one double on stack 41 | 42 | push esi ; save esi 43 | mov esi, ARRAYP ; esi = ARRAYP 44 | xor edx, edx ; edx = array index (initially 0) 45 | 46 | while_loop: 47 | cmp edx, ARRAY_SIZE ; is edx < ARRAY_SIZE? 48 | jnl short quit ; if not, quit loop 49 | ; 50 | ; call fscanf() to read a double into TEMP_DOUBLE 51 | ; fscanf() might change edx so save it 52 | ; 53 | push edx ; save edx 54 | lea eax, TEMP_DOUBLE 55 | push eax ; push &TEMP_DOUBLE 56 | push dword format ; push &format 57 | push FP ; push file pointer 58 | call _fscanf 59 | add esp, 12 60 | pop edx ; restore edx 61 | cmp eax, 1 ; did fscanf return 1? 62 | jne short quit ; if not, quit loop 63 | 64 | ; 65 | ; copy TEMP_DOUBLE into ARRAYP[edx] 66 | ; (The 8-bytes of the double are copied by two 4-byte copies) 67 | ; 68 | mov eax, [ebp - 8] 69 | mov [esi + 8*edx], eax ; first copy lowest 4 bytes 70 | mov eax, [ebp - 4] 71 | mov [esi + 8*edx + 4], eax ; next copy highest 4 bytes 72 | 73 | inc edx 74 | jmp while_loop 75 | 76 | quit: 77 | pop esi ; restore esi 78 | 79 | mov eax, edx ; store return value into eax 80 | 81 | mov esp, ebp 82 | pop ebp 83 | ret 84 | 85 | -------------------------------------------------------------------------------- /examples/cygwin/readt.c: -------------------------------------------------------------------------------- 1 | /* 2 | * file: readt.c 3 | * This program tests the 32-bit read_doubles() assembly procedure. 4 | * It reads the doubles from stdin. 5 | * (Use redirection to read from file.) 6 | */ 7 | 8 | #include 9 | 10 | #include "cdecl.h" 11 | 12 | extern int PRE_CDECL read_doubles( FILE *, double *, int ) POST_CDECL; 13 | 14 | #define MAX 100 15 | 16 | int main() 17 | { 18 | int i,n; 19 | double a[MAX]; 20 | 21 | n = read_doubles(stdin, a, MAX); 22 | 23 | for( i=0; i < n; i++ ) 24 | printf("%3d %g\n", i, a[i]); 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /examples/cygwin/skel.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: skel.asm 5 | ; This file is a skeleton that can be used to start assembly programs. 6 | 7 | %include "asm_io.inc" 8 | segment .data 9 | ; 10 | ; initialized data is put in the data segment here 11 | ; 12 | 13 | 14 | segment .bss 15 | ; 16 | ; uninitialized data is put in the bss segment 17 | ; 18 | 19 | 20 | 21 | 22 | segment .text 23 | global _asm_main 24 | _asm_main: 25 | enter 0,0 ; setup routine 26 | pusha 27 | 28 | ; 29 | ; code is put in the text segment. Do not modify the code before 30 | ; or after this comment. 31 | ; 32 | 33 | popa 34 | mov eax, 0 ; return back to C 35 | leave 36 | ret 37 | 38 | 39 | -------------------------------------------------------------------------------- /examples/cygwin/sub1.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: sub1.asm 5 | ; Subprogram example program 6 | ; 7 | ; To create executable: 8 | ; Using djgpp: 9 | ; nasm -f coff sub1.asm 10 | ; gcc -o sub1 sub1.o driver.c asm_io.o 11 | ; 12 | 13 | %include "asm_io.inc" 14 | 15 | segment .data 16 | prompt1 db "Enter a number: ", 0 ; don't forget nul terminator 17 | prompt2 db "Enter another number: ", 0 18 | outmsg1 db "You entered ", 0 19 | outmsg2 db " and ", 0 20 | outmsg3 db ", the sum of these is ", 0 21 | 22 | segment .bss 23 | ; 24 | ; These labels refer to double words used to store the inputs 25 | ; 26 | input1 resd 1 27 | input2 resd 1 28 | 29 | 30 | 31 | segment .text 32 | global _asm_main 33 | _asm_main: 34 | enter 0,0 ; setup routine 35 | pusha 36 | 37 | mov eax, prompt1 ; print out prompt 38 | call print_string 39 | 40 | mov ebx, input1 ; store address of input1 into ebx 41 | mov ecx, ret1 ; store return address into ecx 42 | jmp short get_int ; read integer 43 | ret1: 44 | mov eax, prompt2 ; print out prompt 45 | call print_string 46 | 47 | mov ebx, input2 48 | mov ecx, $ + 7 ; ecx = this address + 7 49 | jmp short get_int 50 | 51 | mov eax, [input1] ; eax = dword at input1 52 | add eax, [input2] ; eax += dword at input2 53 | mov ebx, eax ; ebx = eax 54 | ; 55 | ; next print out result message as series of steps 56 | ; 57 | 58 | mov eax, outmsg1 59 | call print_string ; print out first message 60 | mov eax, [input1] 61 | call print_int ; print out input1 62 | mov eax, outmsg2 63 | call print_string ; print out second message 64 | mov eax, [input2] 65 | call print_int ; print out input2 66 | mov eax, outmsg3 67 | call print_string ; print out third message 68 | mov eax, ebx 69 | call print_int ; print out sum (ebx) 70 | call print_nl ; print new-line 71 | 72 | popa 73 | mov eax, 0 ; return back to C 74 | leave 75 | ret 76 | ; 77 | ; subprogram get_int 78 | ; Parameters: 79 | ; ebx - address of dword to store integer into 80 | ; ecx - address of instruction to return to 81 | ; Notes: 82 | ; value of eax is destroyed 83 | get_int: 84 | call read_int 85 | mov [ebx], eax ; store input into memory 86 | jmp ecx ; jump back to caller 87 | 88 | 89 | -------------------------------------------------------------------------------- /examples/cygwin/sub2.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: sub2.asm 5 | ; Subprogram example program 6 | ; 7 | ; To create executable: 8 | ; Using djgpp: 9 | ; nasm -f coff sub2.asm 10 | ; gcc -o sub1 sub2.o driver.c asm_io.o 11 | ; 12 | ; Using Borland C/C++ 13 | ; nasm -f obj sub2.asm 14 | ; bcc32 sub2.obj driver.c asm_io.obj 15 | 16 | %include "asm_io.inc" 17 | 18 | segment .data 19 | prompt1 db "Enter a number: ", 0 ; don't forget nul terminator 20 | prompt2 db "Enter another number: ", 0 21 | outmsg1 db "You entered ", 0 22 | outmsg2 db " and ", 0 23 | outmsg3 db ", the sum of these is ", 0 24 | 25 | segment .bss 26 | ; 27 | ; These labels refer to double words used to store the inputs 28 | ; 29 | input1 resd 1 30 | input2 resd 1 31 | 32 | 33 | 34 | segment .text 35 | global _asm_main 36 | _asm_main: 37 | enter 0,0 ; setup routine 38 | pusha 39 | 40 | mov eax, prompt1 ; print out prompt 41 | call print_string 42 | 43 | mov ebx, input1 ; store address of input1 into ebx 44 | call get_int ; read integer 45 | 46 | mov eax, prompt2 ; print out prompt 47 | call print_string 48 | 49 | mov ebx, input2 50 | call get_int 51 | 52 | mov eax, [input1] ; eax = dword at input1 53 | add eax, [input2] ; eax += dword at input2 54 | mov ebx, eax ; ebx = eax 55 | ; 56 | ; next print out result message as series of steps 57 | ; 58 | 59 | mov eax, outmsg1 60 | call print_string ; print out first message 61 | mov eax, [input1] 62 | call print_int ; print out input1 63 | mov eax, outmsg2 64 | call print_string ; print out second message 65 | mov eax, [input2] 66 | call print_int ; print out input2 67 | mov eax, outmsg3 68 | call print_string ; print out third message 69 | mov eax, ebx 70 | call print_int ; print out sum (ebx) 71 | call print_nl ; print new-line 72 | 73 | popa 74 | mov eax, 0 ; return back to C 75 | leave 76 | ret 77 | ; 78 | ; subprogram get_int 79 | ; Parameters: 80 | ; ebx - address of word to store integer into 81 | ; Notes: 82 | ; value of eax is destroyed 83 | get_int: 84 | call read_int 85 | mov [ebx], eax ; store input into memory 86 | ret ; jump back to caller 87 | 88 | 89 | -------------------------------------------------------------------------------- /examples/cygwin/sub4.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: sub4.asm 5 | ; Subprogram example 6 | 7 | %include "asm_io.inc" 8 | 9 | ; 10 | ; subprogram get_int 11 | ; Parameters (in order pushed on stack) 12 | ; number of input (at [ebp + 12]) 13 | ; address of word to store input into (at [ebp + 8]) 14 | ; Notes: 15 | ; values of eax and ebx are destroyed 16 | segment .data 17 | prompt db ") Enter an integer number (0 to quit): ", 0 18 | 19 | segment .bss 20 | 21 | 22 | 23 | segment .text 24 | global get_int, print_sum 25 | get_int: 26 | enter 0,0 27 | 28 | mov eax, [ebp + 12] 29 | call print_int 30 | 31 | mov eax, prompt 32 | call print_string 33 | 34 | call read_int 35 | mov ebx, [ebp + 8] 36 | mov [ebx], eax ; store input into memory 37 | 38 | leave 39 | ret ; jump back to caller 40 | 41 | ; subprogram print_sum 42 | ; prints out the sum 43 | ; Parameter: 44 | ; sum to print out (at [ebp+8]) 45 | ; Note: destroys value of eax 46 | ; 47 | segment .data 48 | result db "The sum is ", 0 49 | 50 | segment .text 51 | print_sum: 52 | enter 0,0 53 | 54 | mov eax, result 55 | call print_string 56 | 57 | mov eax, [ebp+8] 58 | call print_int 59 | call print_nl 60 | 61 | leave 62 | ret 63 | 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /examples/cygwin/sub5.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: sub5.asm 5 | ; Subprogram to C interfacing example 6 | 7 | %include "asm_io.inc" 8 | 9 | ; subroutine _calc_sum 10 | ; finds the sum of the integers 1 through n 11 | ; Parameters: 12 | ; n - what to sum up to (at [ebp + 8]) 13 | ; sump - pointer to int to store sum into (at [ebp + 12]) 14 | ; pseudo C code: 15 | ; void calc_sum( int n, int * sump ) 16 | ; { 17 | ; int i, sum = 0; 18 | ; for( i=1; i <= n; i++ ) 19 | ; sum += i; 20 | ; *sump = sum; 21 | ; } 22 | ; 23 | ; To assemble: 24 | ; DJGPP: nasm -f coff sub5.asm 25 | ; Borland: nasm -f obj sub5.asm 26 | 27 | segment .text 28 | global _calc_sum 29 | ; 30 | ; local variable: 31 | ; sum at [ebp-4] 32 | _calc_sum: 33 | enter 4,0 ; allocate room for sum on stack 34 | push ebx ; IMPORTANT! 35 | 36 | mov dword [ebp-4],0 ; sum = 0 37 | dump_stack 1, 2, 4 ; print out stack from ebp-8 to ebp+16 38 | mov ecx, 1 ; ecx is i in pseudocode 39 | for_loop: 40 | cmp ecx, [ebp+8] ; cmp i and n 41 | jnle end_for ; if not i <= n, quit 42 | 43 | add [ebp-4], ecx ; sum += i 44 | inc ecx 45 | jmp short for_loop 46 | 47 | end_for: 48 | mov ebx, [ebp+12] ; ebx = sump 49 | mov eax, [ebp-4] ; eax = sum 50 | mov [ebx], eax 51 | 52 | pop ebx ; restore ebx 53 | leave 54 | ret 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /examples/cygwin/sub6.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: sub6.asm 5 | ; Subprogram to C interfacing example 6 | 7 | ; subroutine _calc_sum 8 | ; finds the sum of the integers 1 through n 9 | ; Parameters: 10 | ; n - what to sum up to (at [ebp + 8]) 11 | ; Return value: 12 | ; value of sum 13 | ; pseudo C code: 14 | ; int calc_sum( int n ) 15 | ; { 16 | ; int i, sum = 0; 17 | ; for( i=1; i <= n; i++ ) 18 | ; sum += i; 19 | ; return sum; 20 | ; } 21 | ; 22 | ; To assemble: 23 | ; DJGPP: nasm -f coff sub6.asm 24 | ; Borland: nasm -f obj sub6.asm 25 | 26 | segment .text 27 | global _calc_sum 28 | ; 29 | ; local variable: 30 | ; sum at [ebp-4] 31 | _calc_sum: 32 | enter 4,0 ; make room for sum on stack 33 | 34 | mov dword [ebp-4],0 ; sum = 0 35 | mov ecx, 1 ; ecx is i in pseudocode 36 | for_loop: 37 | cmp ecx, [ebp+8] ; cmp i and n 38 | jnle end_for ; if not i <= n, quit 39 | 40 | add [ebp-4], ecx ; sum += i 41 | inc ecx 42 | jmp short for_loop 43 | 44 | end_for: 45 | mov eax, [ebp-4] ; eax = sum 46 | 47 | leave 48 | ret 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /examples/cygwin/test_big_int.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * file: big_int_test.cpp 3 | * A small test program for the Big_int class 4 | */ 5 | #include "big_int.hpp" 6 | #include 7 | 8 | // Borland (or at least bcc32 ver 5.2) doesn't support the std namespace 9 | #if ! ( ( defined(__BORLANDC__) && __BORLANDC__ < 0x550 ) || defined(__WATCOMC__) ) 10 | using namespace std; 11 | #endif 12 | 13 | int main() 14 | { 15 | try { 16 | // 12345678901234567890 17 | Big_int b(5,"8000000000000a00b"); 18 | Big_int a(5,"80000000000010230"); 19 | Big_int c = a + b; 20 | cout << a << " + " << b << " = " << c << endl; 21 | for( int i=0; i < 2; i++ ) { 22 | c = c + a; 23 | cout << "c = " << c << endl; 24 | } 25 | cout << "c-1 = " << c - Big_int(5,1) << endl; 26 | Big_int d(5, "12345678"); 27 | cout << "d = " << d << endl; 28 | cout << "c == d " << (c == d) << endl; 29 | cout << "c > d " << (c > d) << endl; 30 | } 31 | catch( const char * str ) { 32 | cerr << "Caught: " << str << endl; 33 | } 34 | catch( Big_int::Overflow ) { 35 | cerr << "Overflow" << endl; 36 | } 37 | catch( Big_int::Size_mismatch ) { 38 | cerr << "Size mismatch" << endl; 39 | } 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /examples/djgpp-ex.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/humanshell/assembly/474346d24ed2e2abb0e4edd9dc085e6b84104001/examples/djgpp-ex.zip -------------------------------------------------------------------------------- /examples/djgpp/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Djgpp makefile 3 | # Use with make 4 | # 5 | 6 | .SUFFIXES: 7 | .SUFFIXES: .o .asm .cpp .c 8 | 9 | AS=nasm 10 | ASFLAGS= -f coff 11 | CFLAGS= 12 | CC=gcc 13 | CXX=g++ 14 | CXXFLAGS= 15 | 16 | .asm.o: 17 | $(AS) $(ASFLAGS) $*.asm 18 | 19 | .cpp.o: 20 | $(CXX) -c $(CXXFLAGS) $*.cpp 21 | 22 | .c.o: 23 | $(CC) -c $(CFLAGS) $*.c 24 | 25 | 26 | all: prime math sub1 sub2 sub3 sub4 sub5 sub6 first memex dmaxt asm_io.o fprime quadt test_big_int 27 | 28 | prime: driver.o prime.o asm_io.o 29 | $(CC) $(CFLAGS) -o prime driver.o prime.o asm_io.o 30 | 31 | math : driver.o math.o asm_io.o 32 | $(CC) $(CFLAGS) -o math driver.o math.o asm_io.o 33 | 34 | first : driver.o first.o asm_io.o 35 | $(CC) $(CFLAGS) -o first driver.o first.o asm_io.o 36 | 37 | sub1 : driver.o sub1.o asm_io.o 38 | $(CC) $(CFLAGS) -o sub1 driver.o sub1.o asm_io.o 39 | 40 | sub2 : driver.o sub2.o asm_io.o 41 | $(CC) $(CFLAGS) -o sub2 driver.o sub2.o asm_io.o 42 | 43 | sub3 : driver.o sub3.o asm_io.o 44 | $(CC) $(CFLAGS) -o sub3 driver.o sub3.o asm_io.o 45 | 46 | sub4 : driver.o sub4.o main4.o asm_io.o 47 | $(CC) $(CFLAGS) -o sub4 driver.o sub4.o main4.o asm_io.o 48 | 49 | sub5 : main5.o sub5.o asm_io.o 50 | $(CC) $(CFLAGS) -o sub5 main5.o sub5.o asm_io.o 51 | 52 | sub6 : main6.o sub6.o 53 | $(CC) $(CFLAGS) -o sub6 main6.o sub6.o 54 | 55 | asm_io.o : asm_io.asm 56 | $(AS) $(ASFLAGS) -d COFF_TYPE asm_io.asm 57 | 58 | array1 : driver.o array1.o array1c.o 59 | $(CC) $(CFLAGS) -o array1 array1.o array1c.o asm_io.o 60 | 61 | memex : memex.o memory.o 62 | $(CC) $(CFLAGS) -o memex memex.o memory.o 63 | 64 | dmaxt : dmaxt.o dmax.o 65 | $(CC) $(CFLAGS) -o dmaxt dmaxt.o dmax.o 66 | 67 | quadt : quadt.o quad.o 68 | $(CC) $(CFLAGS) -o quadt quadt.o quad.o 69 | 70 | readt : readt.o read.o 71 | $(CC) $(CFLAGS) -o readt readt.o read.o 72 | 73 | fprime : fprime.o prime2.o 74 | $(CC) $(CFLAGS) -o fprime fprime.o prime2.o 75 | 76 | test_big_int : test_big_int.o big_int.o big_math.o 77 | $(CXX) $(CXXFLAGS) -o test_big_int test_big_int.o big_int.o big_math.o 78 | 79 | big_int.o : big_int.hpp 80 | 81 | test_big_int.o : big_int.hpp 82 | 83 | first.o : asm_io.inc first.asm 84 | 85 | sub1.o : asm_io.inc 86 | 87 | sub2.o : asm_io.inc 88 | 89 | sub3.o : asm_io.inc 90 | 91 | sub4.o : asm_io.inc 92 | 93 | main4.o : asm_io.inc 94 | 95 | driver.o : driver.c 96 | 97 | 98 | clean : 99 | del *.o -------------------------------------------------------------------------------- /examples/djgpp/array1c.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Driver file for array1.asm file 3 | */ 4 | 5 | #include 6 | 7 | #include "cdecl.h" 8 | 9 | int PRE_CDECL asm_main( void ) POST_CDECL; 10 | void PRE_CDECL dump_line( void ) POST_CDECL; 11 | 12 | int main() 13 | { 14 | int ret_status; 15 | ret_status = asm_main(); 16 | return ret_status; 17 | } 18 | 19 | /* 20 | * function dump_line 21 | * dumps all chars left in current line from input buffer 22 | */ 23 | void dump_line() 24 | { 25 | int ch; 26 | 27 | while( (ch = getchar()) != EOF && ch != '\n') 28 | /* null body*/ ; 29 | } 30 | 31 | -------------------------------------------------------------------------------- /examples/djgpp/asm_io.inc: -------------------------------------------------------------------------------- 1 | extern read_int, print_int, print_string 2 | extern read_char, print_char, print_nl 3 | extern sub_dump_regs, sub_dump_mem, sub_dump_math, sub_dump_stack 4 | 5 | %macro dump_regs 1 6 | push dword %1 7 | call sub_dump_regs 8 | %endmacro 9 | 10 | 11 | ; 12 | ; usage: dump_mem label, start-address, # paragraphs 13 | %macro dump_mem 3 14 | push dword %1 15 | push dword %2 16 | push dword %3 17 | call sub_dump_mem 18 | %endmacro 19 | 20 | %macro dump_math 1 21 | push dword %1 22 | call sub_dump_math 23 | %endmacro 24 | 25 | %macro dump_stack 3 26 | push dword %3 27 | push dword %2 28 | push dword %1 29 | call sub_dump_stack 30 | %endmacro -------------------------------------------------------------------------------- /examples/djgpp/asm_io.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/humanshell/assembly/474346d24ed2e2abb0e4edd9dc085e6b84104001/examples/djgpp/asm_io.o -------------------------------------------------------------------------------- /examples/djgpp/bitcount.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* 4 | * function bit_count 5 | * Counts the number of bits on (i.e., = 1) in an unsigned int 6 | * (This code assumes that an int is 32-bits!) 7 | * Parameter: 8 | * x - number to count bits of 9 | * Return value: 10 | * number of bits on in x 11 | */ 12 | int bit_count(unsigned int x ) 13 | { 14 | static unsigned int mask[] = { 0x55555555, 15 | 0x33333333, 16 | 0x0F0F0F0F, 17 | 0x00FF00FF, 18 | 0x0000FFFF }; 19 | int i; 20 | int shift; /* number of positions to shift to right */ 21 | 22 | for( i=0, shift=1; i < 5; i++, shift *= 2 ) 23 | x = (x & mask[i]) + ( (x >> shift) & mask[i] ); 24 | return x; 25 | } 26 | 27 | 28 | int main() 29 | { 30 | unsigned int x; 31 | 32 | printf("Enter a number: "); 33 | scanf("%i", &x); 34 | printf("There are %d bits on in %X\n", bit_count(x), x); 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /examples/djgpp/bitcount2.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static unsigned char byte_bit_count[256]; /* lookup table */ 4 | 5 | void initialize_count_bits() 6 | { 7 | int cnt, i, data; 8 | 9 | for( i = 0; i < 256; i++ ) { 10 | cnt = 0; 11 | data = i; 12 | while( data != 0 ) { 13 | data = data & (data - 1); 14 | cnt++; 15 | } 16 | byte_bit_count[i] = cnt; 17 | printf("%d %d\n", i, byte_bit_count[i]); 18 | } 19 | } 20 | 21 | int count_bits( unsigned int data ) 22 | { 23 | const unsigned char * dword = ( unsigned char *) & data; 24 | 25 | return byte_bit_count[dword[0]] + byte_bit_count[dword[1]] + 26 | byte_bit_count[dword[2]] + byte_bit_count[dword[3]]; 27 | } 28 | 29 | int main() 30 | { 31 | unsigned int x; 32 | 33 | initialize_count_bits(); 34 | printf("Enter a number: "); 35 | scanf("%i", &x); 36 | printf("There are %d bits on in %X\n", count_bits(x), x); 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /examples/djgpp/cdecl.h: -------------------------------------------------------------------------------- 1 | #ifndef CDECL_HEADER_FILE 2 | #define CDECL_HEADER_FILE 3 | 4 | /* 5 | * Define macros to specify the standard C calling convention 6 | * The macros are designed so that they will work with all 7 | * supported C/C++ compilers. 8 | * 9 | * To use define your function prototype like this: 10 | * 11 | * return_type PRE_CDECL func_name( args ) POST_CDECL; 12 | * 13 | * For example: 14 | * 15 | * int PRE_CDECL f( int x, int y) POST_CDECL; 16 | */ 17 | 18 | 19 | #if defined(__GNUC__) 20 | # define PRE_CDECL 21 | # define POST_CDECL __attribute__((cdecl)) 22 | #else 23 | # define PRE_CDECL __cdecl 24 | # define POST_CDECL 25 | #endif 26 | 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /examples/djgpp/dmax.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: dmax.asm 5 | 6 | global _dmax 7 | 8 | 9 | 10 | segment .text 11 | ; function _dmax 12 | ; returns the larger of its two double arguments 13 | ; C prototype 14 | ; double dmax( double d1, double d2 ) 15 | ; Parameters: 16 | ; d1 - first double 17 | ; d2 - second double 18 | ; Return value: 19 | ; larger of d1 and d2 (in ST0) 20 | 21 | ; next, some helpful symbols are defined 22 | 23 | %define d1 [ebp+8] 24 | %define d2 [ebp+16] 25 | 26 | _dmax: 27 | enter 0, 0 28 | 29 | fld qword d2 30 | fld qword d1 ; ST0 = d1, ST1 = d2 31 | fcomip st1 ; ST0 = d2 32 | jna short d2_bigger 33 | fcomp st0 ; pop d2 from stack 34 | fld qword d1 ; ST0 = d1 35 | 36 | d2_bigger: ; if d2 is bigger, nothing to do 37 | 38 | exit: 39 | leave 40 | ret 41 | 42 | 43 | -------------------------------------------------------------------------------- /examples/djgpp/dmaxt.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "cdecl.h" 4 | 5 | double PRE_CDECL dmax( double, double ) POST_CDECL; 6 | 7 | int main() 8 | { 9 | double d1, d2; 10 | 11 | printf("Enter two doubles: "); 12 | scanf("%lf %lf", &d1, &d2); 13 | 14 | printf("The larger of %g and %g is %g\n", d1, d2, dmax(d1,d2)); 15 | return 0; 16 | } 17 | 18 | -------------------------------------------------------------------------------- /examples/djgpp/driver.c: -------------------------------------------------------------------------------- 1 | #include "cdecl.h" 2 | 3 | int PRE_CDECL asm_main( void ) POST_CDECL; 4 | 5 | int main() 6 | { 7 | int ret_status; 8 | ret_status = asm_main(); 9 | return ret_status; 10 | } 11 | -------------------------------------------------------------------------------- /examples/djgpp/fprime.c: -------------------------------------------------------------------------------- 1 | /* 2 | * file: fprime.c 3 | * This program calculates prime numbers 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | #include "cdecl.h" 10 | 11 | /* 12 | * function find_primes 13 | * finds the indicated number of primes 14 | * Parameters: 15 | * a - array to hold primes 16 | * n - how many primes to find 17 | */ 18 | extern void PRE_CDECL find_primes( int * a, unsigned n ) POST_CDECL; 19 | 20 | int main() 21 | { 22 | int status; 23 | unsigned i; 24 | unsigned max; 25 | int * a; 26 | 27 | printf("How many primes do you wish to find? "); 28 | scanf("%u", &max); 29 | 30 | a = calloc( sizeof(int), max); 31 | 32 | if ( a ) { 33 | 34 | find_primes(a,max); 35 | 36 | /* 37 | * print out the last 20 primes found 38 | */ 39 | for(i= ( max > 20 ) ? max - 20 : 0; i < max; i++ ) 40 | printf("%3d %d\n", i+1, a[i]); 41 | 42 | free(a); 43 | status = 0; 44 | } 45 | else { 46 | fprintf(stderr, "Can not create array of %u ints\n", max); 47 | status = 1; 48 | } 49 | 50 | return status; 51 | } 52 | -------------------------------------------------------------------------------- /examples/djgpp/main4.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: main4.asm 5 | ; Multi-module subprogram example program 6 | ; 7 | ; To create executable: 8 | ; Using djgpp: 9 | ; nasm -f coff sub4.asm 10 | ; nasm -f coff main4.asm 11 | ; gcc -o sub4 sub4.o main4.o driver.c asm_io.o 12 | ; 13 | ; Using Borland C/C++ 14 | ; nasm -f obj sub4.asm 15 | ; nasm -f obj main4.asm 16 | ; bcc32 sub4.obj main4.asm driver.c asm_io.obj 17 | 18 | %include "asm_io.inc" 19 | 20 | segment .data 21 | sum dd 0 22 | 23 | segment .bss 24 | input resd 1 25 | 26 | 27 | 28 | ; 29 | ; psuedo-code algorithm 30 | ; i = 1; 31 | ; sum = 0; 32 | ; while( get_int(i, &input), input != 0 ) { 33 | ; sum += input; 34 | ; i++; 35 | ; } 36 | ; print_sum(num); 37 | 38 | segment .text 39 | global _asm_main 40 | extern get_int, print_sum 41 | _asm_main: 42 | enter 0,0 ; setup routine 43 | pusha 44 | 45 | mov edx, 1 ; edx is 'i' in pseudo-code 46 | while_loop: 47 | push edx ; save i on stack 48 | push dword input ; push address on input on stack 49 | call get_int 50 | add esp, 8 ; remove i and &input from stack 51 | 52 | mov eax, [input] 53 | cmp eax, 0 54 | je end_while 55 | 56 | add [sum], eax ; sum += input 57 | 58 | inc edx 59 | jmp short while_loop 60 | 61 | end_while: 62 | push dword [sum] ; push value of sum onto stack 63 | call print_sum 64 | pop ecx ; remove [sum] from stack 65 | 66 | popa 67 | leave 68 | ret 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /examples/djgpp/main5.c: -------------------------------------------------------------------------------- 1 | /* 2 | * file: main5.c 3 | * main C program that uses assembly routine in sub5.asm 4 | * to create executable: 5 | * DJGPP: gcc -o sub5 main5.c sub5.o asm_io.o 6 | * Borland: bcc32 sub5.obj main5.c asm_io.obj 7 | */ 8 | 9 | #include 10 | 11 | #include "cdecl.h" 12 | 13 | void PRE_CDECL calc_sum( int, int * ) POST_CDECL; /* prototype for assembly routine */ 14 | 15 | int main( void ) 16 | { 17 | int n, sum; 18 | 19 | printf("Sum integers up to: "); 20 | scanf("%d", &n); 21 | calc_sum(n, &sum); 22 | printf("Sum is %d\n", sum); 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /examples/djgpp/main6.c: -------------------------------------------------------------------------------- 1 | /* 2 | * file: main6.c 3 | * main C program that uses assembly routine in sub5.asm 4 | * to create executable: 5 | * DJGPP: gcc -o sub5 main5.c sub5.o 6 | * Borland: bcc32 sub5.obj main5.c 7 | */ 8 | 9 | #include 10 | 11 | #include "cdecl.h" 12 | 13 | int PRE_CDECL calc_sum( int ) POST_CDECL; /* prototype for assembly routine */ 14 | 15 | int main( void ) 16 | { 17 | int n, sum; 18 | 19 | printf("Sum integers up to: "); 20 | scanf("%d", &n); 21 | sum = calc_sum(n); 22 | printf("Sum is %d\n", sum); 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /examples/djgpp/math.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: math.asm 5 | ; This program demonstrates how the integer multiplication and division 6 | ; instructions work. 7 | ; 8 | ; To create executable: 9 | ; nasm -f coff math.asm 10 | ; gcc -o math math.o driver.c asm_io.o 11 | 12 | %include "asm_io.inc" 13 | 14 | segment .data 15 | ; 16 | ; Output strings 17 | ; 18 | prompt db "Enter a number: ", 0 19 | square_msg db "Square of input is ", 0 20 | cube_msg db "Cube of input is ", 0 21 | cube25_msg db "Cube of input times 25 is ", 0 22 | quot_msg db "Quotient of cube/100 is ", 0 23 | rem_msg db "Remainder of cube/100 is ", 0 24 | neg_msg db "The negation of the remainder is ", 0 25 | 26 | segment .bss 27 | input resd 1 28 | 29 | 30 | segment .text 31 | global _asm_main 32 | _asm_main: 33 | enter 0,0 ; setup routine 34 | pusha 35 | 36 | mov eax, prompt 37 | call print_string 38 | 39 | call read_int 40 | mov [input], eax 41 | 42 | imul eax ; edx:eax = eax * eax 43 | mov ebx, eax ; save answer in ebx 44 | mov eax, square_msg 45 | call print_string 46 | mov eax, ebx 47 | call print_int 48 | call print_nl 49 | 50 | mov ebx, eax 51 | imul ebx, [input] ; ebx *= [input] 52 | mov eax, cube_msg 53 | call print_string 54 | mov eax, ebx 55 | call print_int 56 | call print_nl 57 | 58 | imul ecx, ebx, 25 ; ecx = ebx*25 59 | mov eax, cube25_msg 60 | call print_string 61 | mov eax, ecx 62 | call print_int 63 | call print_nl 64 | 65 | mov eax, ebx 66 | cdq ; initialize edx by sign extension 67 | mov ecx, 100 ; can't divide by immediate value 68 | idiv ecx ; edx:eax / ecx 69 | mov ecx, eax ; save quotient into ecx 70 | mov eax, quot_msg 71 | call print_string 72 | mov eax, ecx 73 | call print_int 74 | call print_nl 75 | mov eax, rem_msg 76 | call print_string 77 | mov eax, edx 78 | call print_int 79 | call print_nl 80 | 81 | neg edx ; negate the remainder 82 | mov eax, neg_msg 83 | call print_string 84 | mov eax, edx 85 | call print_int 86 | call print_nl 87 | 88 | popa 89 | mov eax, 0 ; return back to C 90 | leave 91 | ret 92 | 93 | 94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /examples/djgpp/max.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: max.asm 5 | ; This example demostrates how to avoid conditional branches 6 | 7 | %include "asm_io.inc" 8 | segment .data 9 | 10 | message1 db "Enter a number: ",0 11 | message2 db "Enter another number: ", 0 12 | message3 db "The larger number is: ", 0 13 | 14 | segment .bss 15 | 16 | input1 resd 1 ; first number entered 17 | 18 | 19 | 20 | segment .text 21 | global _asm_main 22 | _asm_main: 23 | enter 0,0 ; setup routine 24 | pusha 25 | 26 | mov eax, message1 ; print out first message 27 | call print_string 28 | call read_int ; input first number 29 | mov [input1], eax 30 | 31 | mov eax, message2 ; print out second message 32 | call print_string 33 | call read_int ; input second number (in eax) 34 | 35 | xor ebx, ebx ; ebx = 0 36 | cmp eax, [input1] ; compare second and first number 37 | setg bl ; ebx = (input2 > input1) ? 1 : 0 38 | neg ebx ; ebx = (input2 > input1) ? 0xFFFFFFFF : 0 39 | mov ecx, ebx ; ecx = (input2 > input1) ? 0xFFFFFFFF : 0 40 | and ecx, eax ; ecx = (input2 > input1) ? input2 : 0 41 | not ebx ; ebx = (input2 > input1) ? 0 : 0xFFFFFFFF 42 | and ebx, [input1] ; ebx = (input2 > input1) ? 0 : input1 43 | or ecx, ebx ; ecx = (input2 > input1) ? input2 : input1 44 | 45 | mov eax, message3 ; print out result 46 | call print_string 47 | mov eax, ecx 48 | call print_int 49 | call print_nl 50 | 51 | popa 52 | mov eax, 0 ; return back to C 53 | leave 54 | ret 55 | 56 | 57 | -------------------------------------------------------------------------------- /examples/djgpp/memex.c: -------------------------------------------------------------------------------- 1 | /* 2 | * file: memex.c 3 | */ 4 | 5 | #include 6 | 7 | #include "cdecl.h" 8 | 9 | #define STR_SIZE 30 10 | /* 11 | * prototypes 12 | */ 13 | 14 | void PRE_CDECL asm_copy( void *, 15 | const void *, 16 | unsigned ) POST_CDECL; 17 | 18 | void * PRE_CDECL asm_find( const void *, 19 | char target, 20 | unsigned ) POST_CDECL; 21 | 22 | unsigned PRE_CDECL asm_strlen( const char * ) POST_CDECL; 23 | 24 | void PRE_CDECL asm_strcpy( char *, 25 | const char * ) POST_CDECL; 26 | 27 | int main() 28 | { 29 | char st1[STR_SIZE] = "test string"; 30 | char st2[STR_SIZE]; 31 | char * st; 32 | char ch; 33 | 34 | asm_copy(st2, st1, STR_SIZE); /* copy all 30 chars of string */ 35 | printf("%s\n", st2); 36 | 37 | printf("Enter a char: "); /* look for byte in string */ 38 | scanf("%c%*[^\n]", &ch); 39 | st = asm_find(st2, ch, STR_SIZE); 40 | if ( st ) 41 | printf("Found it: %s\n", st); 42 | else 43 | printf("Not found\n"); 44 | 45 | st1[0] = 0; 46 | printf("Enter string:"); 47 | scanf("%s", st1); 48 | printf("len = %u\n", asm_strlen(st1)); 49 | 50 | asm_strcpy( st2, st1); /* copy meaningful data in string */ 51 | printf("%s\n", st2 ); 52 | 53 | return 0; 54 | } 55 | 56 | -------------------------------------------------------------------------------- /examples/djgpp/quadt.c: -------------------------------------------------------------------------------- 1 | /* 2 | * file: quadt.c 3 | * Test file for quad.asm 4 | */ 5 | 6 | #include 7 | 8 | #include "cdecl.h" 9 | 10 | int PRE_CDECL quadratic( double, double, double, double *, double *) POST_CDECL; 11 | 12 | int main() 13 | { 14 | double a,b,c, root1, root2; 15 | 16 | printf("Enter a, b, c: "); 17 | scanf("%lf %lf %lf", &a, &b, &c); 18 | if (quadratic( a, b, c, &root1, &root2) ) 19 | printf("roots: %.10g %.10g\n", root1, root2); 20 | else 21 | printf("No real roots\n"); 22 | return 0; 23 | } 24 | 25 | -------------------------------------------------------------------------------- /examples/djgpp/read.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: read.asm 5 | ; This subroutine reads an array of doubles from a file 6 | 7 | segment .data 8 | format db "%lf", 0 ; format for fscanf() 9 | 10 | segment .bss 11 | 12 | 13 | 14 | segment .text 15 | global _read_doubles 16 | extern _fscanf 17 | 18 | %define SIZEOF_DOUBLE 8 19 | %define FP dword [ebp + 8] 20 | %define ARRAYP dword [ebp + 12] 21 | %define ARRAY_SIZE dword [ebp + 16] 22 | %define TEMP_DOUBLE [ebp - 8] 23 | 24 | ; 25 | ; function _read_doubles 26 | ; C prototype: 27 | ; int read_doubles( FILE * fp, double * arrayp, int array_size ); 28 | ; This function reads doubles from a text file into an array, until 29 | ; EOF or array is full. 30 | ; Parameters: 31 | ; fp - FILE pointer to read from (must be open for input) 32 | ; arrayp - pointer to double array to read into 33 | ; array_size - number of elements in array 34 | ; Return value: 35 | ; number of doubles stored into array (in EAX) 36 | 37 | _read_doubles: 38 | push ebp 39 | mov ebp,esp 40 | sub esp, SIZEOF_DOUBLE ; define one double on stack 41 | 42 | push esi ; save esi 43 | mov esi, ARRAYP ; esi = ARRAYP 44 | xor edx, edx ; edx = array index (initially 0) 45 | 46 | while_loop: 47 | cmp edx, ARRAY_SIZE ; is edx < ARRAY_SIZE? 48 | jnl short quit ; if not, quit loop 49 | ; 50 | ; call fscanf() to read a double into TEMP_DOUBLE 51 | ; fscanf() might change edx so save it 52 | ; 53 | push edx ; save edx 54 | lea eax, TEMP_DOUBLE 55 | push eax ; push &TEMP_DOUBLE 56 | push dword format ; push &format 57 | push FP ; push file pointer 58 | call _fscanf 59 | add esp, 12 60 | pop edx ; restore edx 61 | cmp eax, 1 ; did fscanf return 1? 62 | jne short quit ; if not, quit loop 63 | 64 | ; 65 | ; copy TEMP_DOUBLE into ARRAYP[edx] 66 | ; (The 8-bytes of the double are copied by two 4-byte copies) 67 | ; 68 | mov eax, [ebp - 8] 69 | mov [esi + 8*edx], eax ; first copy lowest 4 bytes 70 | mov eax, [ebp - 4] 71 | mov [esi + 8*edx + 4], eax ; next copy highest 4 bytes 72 | 73 | inc edx 74 | jmp while_loop 75 | 76 | quit: 77 | pop esi ; restore esi 78 | 79 | mov eax, edx ; store return value into eax 80 | 81 | mov esp, ebp 82 | pop ebp 83 | ret 84 | 85 | -------------------------------------------------------------------------------- /examples/djgpp/readt.c: -------------------------------------------------------------------------------- 1 | /* 2 | * file: readt.c 3 | * This program tests the 32-bit read_doubles() assembly procedure. 4 | * It reads the doubles from stdin. 5 | * (Use redirection to read from file.) 6 | */ 7 | 8 | #include 9 | 10 | #include "cdecl.h" 11 | 12 | extern int PRE_CDECL read_doubles( FILE *, double *, int ) POST_CDECL; 13 | 14 | #define MAX 100 15 | 16 | int main() 17 | { 18 | int i,n; 19 | double a[MAX]; 20 | 21 | n = read_doubles(stdin, a, MAX); 22 | 23 | for( i=0; i < n; i++ ) 24 | printf("%3d %g\n", i, a[i]); 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /examples/djgpp/skel.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: skel.asm 5 | ; This file is a skeleton that can be used to start assembly programs. 6 | 7 | %include "asm_io.inc" 8 | segment .data 9 | ; 10 | ; initialized data is put in the data segment here 11 | ; 12 | 13 | 14 | segment .bss 15 | ; 16 | ; uninitialized data is put in the bss segment 17 | ; 18 | 19 | 20 | 21 | 22 | segment .text 23 | global _asm_main 24 | _asm_main: 25 | enter 0,0 ; setup routine 26 | pusha 27 | 28 | ; 29 | ; code is put in the text segment. Do not modify the code before 30 | ; or after this comment. 31 | ; 32 | 33 | popa 34 | mov eax, 0 ; return back to C 35 | leave 36 | ret 37 | 38 | 39 | -------------------------------------------------------------------------------- /examples/djgpp/sub1.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: sub1.asm 5 | ; Subprogram example program 6 | ; 7 | ; To create executable: 8 | ; Using djgpp: 9 | ; nasm -f coff sub1.asm 10 | ; gcc -o sub1 sub1.o driver.c asm_io.o 11 | ; 12 | 13 | %include "asm_io.inc" 14 | 15 | segment .data 16 | prompt1 db "Enter a number: ", 0 ; don't forget nul terminator 17 | prompt2 db "Enter another number: ", 0 18 | outmsg1 db "You entered ", 0 19 | outmsg2 db " and ", 0 20 | outmsg3 db ", the sum of these is ", 0 21 | 22 | segment .bss 23 | ; 24 | ; These labels refer to double words used to store the inputs 25 | ; 26 | input1 resd 1 27 | input2 resd 1 28 | 29 | 30 | 31 | segment .text 32 | global _asm_main 33 | _asm_main: 34 | enter 0,0 ; setup routine 35 | pusha 36 | 37 | mov eax, prompt1 ; print out prompt 38 | call print_string 39 | 40 | mov ebx, input1 ; store address of input1 into ebx 41 | mov ecx, ret1 ; store return address into ecx 42 | jmp short get_int ; read integer 43 | ret1: 44 | mov eax, prompt2 ; print out prompt 45 | call print_string 46 | 47 | mov ebx, input2 48 | mov ecx, $ + 7 ; ecx = this address + 7 49 | jmp short get_int 50 | 51 | mov eax, [input1] ; eax = dword at input1 52 | add eax, [input2] ; eax += dword at input2 53 | mov ebx, eax ; ebx = eax 54 | ; 55 | ; next print out result message as series of steps 56 | ; 57 | 58 | mov eax, outmsg1 59 | call print_string ; print out first message 60 | mov eax, [input1] 61 | call print_int ; print out input1 62 | mov eax, outmsg2 63 | call print_string ; print out second message 64 | mov eax, [input2] 65 | call print_int ; print out input2 66 | mov eax, outmsg3 67 | call print_string ; print out third message 68 | mov eax, ebx 69 | call print_int ; print out sum (ebx) 70 | call print_nl ; print new-line 71 | 72 | popa 73 | mov eax, 0 ; return back to C 74 | leave 75 | ret 76 | ; 77 | ; subprogram get_int 78 | ; Parameters: 79 | ; ebx - address of dword to store integer into 80 | ; ecx - address of instruction to return to 81 | ; Notes: 82 | ; value of eax is destroyed 83 | get_int: 84 | call read_int 85 | mov [ebx], eax ; store input into memory 86 | jmp ecx ; jump back to caller 87 | 88 | 89 | -------------------------------------------------------------------------------- /examples/djgpp/sub2.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: sub2.asm 5 | ; Subprogram example program 6 | ; 7 | ; To create executable: 8 | ; Using djgpp: 9 | ; nasm -f coff sub2.asm 10 | ; gcc -o sub1 sub2.o driver.c asm_io.o 11 | ; 12 | ; Using Borland C/C++ 13 | ; nasm -f obj sub2.asm 14 | ; bcc32 sub2.obj driver.c asm_io.obj 15 | 16 | %include "asm_io.inc" 17 | 18 | segment .data 19 | prompt1 db "Enter a number: ", 0 ; don't forget nul terminator 20 | prompt2 db "Enter another number: ", 0 21 | outmsg1 db "You entered ", 0 22 | outmsg2 db " and ", 0 23 | outmsg3 db ", the sum of these is ", 0 24 | 25 | segment .bss 26 | ; 27 | ; These labels refer to double words used to store the inputs 28 | ; 29 | input1 resd 1 30 | input2 resd 1 31 | 32 | 33 | 34 | segment .text 35 | global _asm_main 36 | _asm_main: 37 | enter 0,0 ; setup routine 38 | pusha 39 | 40 | mov eax, prompt1 ; print out prompt 41 | call print_string 42 | 43 | mov ebx, input1 ; store address of input1 into ebx 44 | call get_int ; read integer 45 | 46 | mov eax, prompt2 ; print out prompt 47 | call print_string 48 | 49 | mov ebx, input2 50 | call get_int 51 | 52 | mov eax, [input1] ; eax = dword at input1 53 | add eax, [input2] ; eax += dword at input2 54 | mov ebx, eax ; ebx = eax 55 | ; 56 | ; next print out result message as series of steps 57 | ; 58 | 59 | mov eax, outmsg1 60 | call print_string ; print out first message 61 | mov eax, [input1] 62 | call print_int ; print out input1 63 | mov eax, outmsg2 64 | call print_string ; print out second message 65 | mov eax, [input2] 66 | call print_int ; print out input2 67 | mov eax, outmsg3 68 | call print_string ; print out third message 69 | mov eax, ebx 70 | call print_int ; print out sum (ebx) 71 | call print_nl ; print new-line 72 | 73 | popa 74 | mov eax, 0 ; return back to C 75 | leave 76 | ret 77 | ; 78 | ; subprogram get_int 79 | ; Parameters: 80 | ; ebx - address of word to store integer into 81 | ; Notes: 82 | ; value of eax is destroyed 83 | get_int: 84 | call read_int 85 | mov [ebx], eax ; store input into memory 86 | ret ; jump back to caller 87 | 88 | 89 | -------------------------------------------------------------------------------- /examples/djgpp/sub4.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: sub4.asm 5 | ; Subprogram example 6 | 7 | %include "asm_io.inc" 8 | 9 | ; 10 | ; subprogram get_int 11 | ; Parameters (in order pushed on stack) 12 | ; number of input (at [ebp + 12]) 13 | ; address of word to store input into (at [ebp + 8]) 14 | ; Notes: 15 | ; values of eax and ebx are destroyed 16 | segment .data 17 | prompt db ") Enter an integer number (0 to quit): ", 0 18 | 19 | segment .bss 20 | 21 | 22 | 23 | segment .text 24 | global get_int, print_sum 25 | get_int: 26 | enter 0,0 27 | 28 | mov eax, [ebp + 12] 29 | call print_int 30 | 31 | mov eax, prompt 32 | call print_string 33 | 34 | call read_int 35 | mov ebx, [ebp + 8] 36 | mov [ebx], eax ; store input into memory 37 | 38 | leave 39 | ret ; jump back to caller 40 | 41 | ; subprogram print_sum 42 | ; prints out the sum 43 | ; Parameter: 44 | ; sum to print out (at [ebp+8]) 45 | ; Note: destroys value of eax 46 | ; 47 | segment .data 48 | result db "The sum is ", 0 49 | 50 | segment .text 51 | print_sum: 52 | enter 0,0 53 | 54 | mov eax, result 55 | call print_string 56 | 57 | mov eax, [ebp+8] 58 | call print_int 59 | call print_nl 60 | 61 | leave 62 | ret 63 | 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /examples/djgpp/sub5.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: sub5.asm 5 | ; Subprogram to C interfacing example 6 | 7 | %include "asm_io.inc" 8 | 9 | ; subroutine _calc_sum 10 | ; finds the sum of the integers 1 through n 11 | ; Parameters: 12 | ; n - what to sum up to (at [ebp + 8]) 13 | ; sump - pointer to int to store sum into (at [ebp + 12]) 14 | ; pseudo C code: 15 | ; void calc_sum( int n, int * sump ) 16 | ; { 17 | ; int i, sum = 0; 18 | ; for( i=1; i <= n; i++ ) 19 | ; sum += i; 20 | ; *sump = sum; 21 | ; } 22 | ; 23 | ; To assemble: 24 | ; DJGPP: nasm -f coff sub5.asm 25 | ; Borland: nasm -f obj sub5.asm 26 | 27 | segment .text 28 | global _calc_sum 29 | ; 30 | ; local variable: 31 | ; sum at [ebp-4] 32 | _calc_sum: 33 | enter 4,0 ; allocate room for sum on stack 34 | push ebx ; IMPORTANT! 35 | 36 | mov dword [ebp-4],0 ; sum = 0 37 | dump_stack 1, 2, 4 ; print out stack from ebp-8 to ebp+16 38 | mov ecx, 1 ; ecx is i in pseudocode 39 | for_loop: 40 | cmp ecx, [ebp+8] ; cmp i and n 41 | jnle end_for ; if not i <= n, quit 42 | 43 | add [ebp-4], ecx ; sum += i 44 | inc ecx 45 | jmp short for_loop 46 | 47 | end_for: 48 | mov ebx, [ebp+12] ; ebx = sump 49 | mov eax, [ebp-4] ; eax = sum 50 | mov [ebx], eax 51 | 52 | pop ebx ; restore ebx 53 | leave 54 | ret 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /examples/djgpp/sub6.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: sub6.asm 5 | ; Subprogram to C interfacing example 6 | 7 | ; subroutine _calc_sum 8 | ; finds the sum of the integers 1 through n 9 | ; Parameters: 10 | ; n - what to sum up to (at [ebp + 8]) 11 | ; Return value: 12 | ; value of sum 13 | ; pseudo C code: 14 | ; int calc_sum( int n ) 15 | ; { 16 | ; int i, sum = 0; 17 | ; for( i=1; i <= n; i++ ) 18 | ; sum += i; 19 | ; return sum; 20 | ; } 21 | ; 22 | ; To assemble: 23 | ; DJGPP: nasm -f coff sub6.asm 24 | ; Borland: nasm -f obj sub6.asm 25 | 26 | segment .text 27 | global _calc_sum 28 | ; 29 | ; local variable: 30 | ; sum at [ebp-4] 31 | _calc_sum: 32 | enter 4,0 ; make room for sum on stack 33 | 34 | mov dword [ebp-4],0 ; sum = 0 35 | mov ecx, 1 ; ecx is i in pseudocode 36 | for_loop: 37 | cmp ecx, [ebp+8] ; cmp i and n 38 | jnle end_for ; if not i <= n, quit 39 | 40 | add [ebp-4], ecx ; sum += i 41 | inc ecx 42 | jmp short for_loop 43 | 44 | end_for: 45 | mov eax, [ebp-4] ; eax = sum 46 | 47 | leave 48 | ret 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /examples/djgpp/test_big_int.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * file: big_int_test.cpp 3 | * A small test program for the Big_int class 4 | */ 5 | #include "big_int.hpp" 6 | #include 7 | 8 | // Borland (or at least bcc32 ver 5.2) doesn't support the std namespace 9 | #if ! ( ( defined(__BORLANDC__) && __BORLANDC__ < 0x550 ) || defined(__WATCOMC__) ) 10 | using namespace std; 11 | #endif 12 | 13 | int main() 14 | { 15 | try { 16 | // 12345678901234567890 17 | Big_int b(5,"8000000000000a00b"); 18 | Big_int a(5,"80000000000010230"); 19 | Big_int c = a + b; 20 | cout << a << " + " << b << " = " << c << endl; 21 | for( int i=0; i < 2; i++ ) { 22 | c = c + a; 23 | cout << "c = " << c << endl; 24 | } 25 | cout << "c-1 = " << c - Big_int(5,1) << endl; 26 | Big_int d(5, "12345678"); 27 | cout << "d = " << d << endl; 28 | cout << "c == d " << (c == d) << endl; 29 | cout << "c > d " << (c > d) << endl; 30 | } 31 | catch( const char * str ) { 32 | cerr << "Caught: " << str << endl; 33 | } 34 | catch( Big_int::Overflow ) { 35 | cerr << "Overflow" << endl; 36 | } 37 | catch( Big_int::Size_mismatch ) { 38 | cerr << "Size mismatch" << endl; 39 | } 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /examples/linux-ex.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/humanshell/assembly/474346d24ed2e2abb0e4edd9dc085e6b84104001/examples/linux-ex.zip -------------------------------------------------------------------------------- /examples/linux/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Linux makefile 3 | # Use with make 4 | # 5 | 6 | .SUFFIXES: 7 | .SUFFIXES: .o .asm .cpp .c 8 | 9 | AS=nasm 10 | ASFLAGS= -f elf 11 | CFLAGS= 12 | CC=gcc 13 | CXX=g++ 14 | CXXFLAGS= 15 | 16 | .asm.o: 17 | $(AS) $(ASFLAGS) $*.asm 18 | 19 | .cpp.o: 20 | $(CXX) -c $(CXXFLAGS) $*.cpp 21 | 22 | .c.o: 23 | $(CC) -c $(CFLAGS) $*.c 24 | 25 | all: prime math sub1 sub2 sub3 sub4 sub5 sub6 first memex dmaxt asm_io.o fprime quadt test_big_int 26 | 27 | prime: driver.o prime.o asm_io.o 28 | $(CC) $(CFLAGS) -oprime driver.o prime.o asm_io.o 29 | 30 | math : driver.o math.o asm_io.o 31 | $(CC) $(CFLAGS) -omath driver.o math.o asm_io.o 32 | 33 | first : driver.o first.o asm_io.o 34 | $(CC) $(CFLAGS) -ofirst driver.o first.o asm_io.o 35 | 36 | sub1 : driver.o sub1.o asm_io.o 37 | $(CC) $(CFLAGS) -osub1 driver.o sub1.o asm_io.o 38 | 39 | sub2 : driver.o sub2.o asm_io.o 40 | $(CC) $(CFLAGS) -osub2 driver.o sub2.o asm_io.o 41 | 42 | sub3 : driver.o sub3.o asm_io.o 43 | $(CC) $(CFLAGS) -osub3 driver.o sub3.o asm_io.o 44 | 45 | sub4 : driver.o sub4.o main4.o asm_io.o 46 | $(CC) $(CFLAGS) -osub4 driver.o sub4.o main4.o asm_io.o 47 | 48 | sub5 : main5.o sub5.o asm_io.o 49 | $(CC) $(CFLAGS) -osub5 main5.o sub5.o asm_io.o 50 | 51 | sub6 : main6.o sub6.o 52 | $(CC) $(CFLAGS) -osub6 main6.o sub6.o 53 | 54 | asm_io.o : asm_io.asm 55 | $(AS) $(ASFLAGS) -d ELF_TYPE asm_io.asm 56 | 57 | array1 : driver.o array1.o array1c.o 58 | $(CC) $(CFLAGS) -oarray1 array1.o array1c.o asm_io.o 59 | 60 | memex : memex.o memory.o 61 | $(CC) $(CFLAGS) -omemex memex.o memory.o 62 | 63 | dmaxt : dmaxt.o dmax.o 64 | $(CC) $(CFLAGS) -odmaxt dmaxt.o dmax.o 65 | 66 | quadt : quadt.o quad.o 67 | $(CC) $(CFLAGS) -oquadt quadt.o quad.o 68 | 69 | readt : readt.o read.o 70 | $(CC) $(CFLAGS) -oreadt readt.o read.o 71 | 72 | fprime : fprime.o prime2.o 73 | $(CC) $(CFLAGS) -ofprime fprime.o prime2.o 74 | 75 | test_big_int : test_big_int.o big_int.o big_math.o 76 | $(CXX) $(CXXFLAGS) -otest_big_int test_big_int.o big_int.o big_math.o 77 | 78 | big_int.o : big_int.hpp 79 | 80 | test_big_int.o : big_int.hpp 81 | 82 | first.o : asm_io.inc first.asm 83 | 84 | sub1.o : asm_io.inc 85 | 86 | sub2.o : asm_io.inc 87 | 88 | sub3.o : asm_io.inc 89 | 90 | sub4.o : asm_io.inc 91 | 92 | main4.o : asm_io.inc 93 | 94 | driver.o : driver.c 95 | 96 | 97 | clean : 98 | rm *.o 99 | -------------------------------------------------------------------------------- /examples/linux/array1c.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Driver file for array1.asm file 3 | */ 4 | 5 | #include 6 | 7 | #include "cdecl.h" 8 | 9 | int PRE_CDECL asm_main( void ) POST_CDECL; 10 | void PRE_CDECL dump_line( void ) POST_CDECL; 11 | 12 | int main() 13 | { 14 | int ret_status; 15 | ret_status = asm_main(); 16 | return ret_status; 17 | } 18 | 19 | /* 20 | * function dump_line 21 | * dumps all chars left in current line from input buffer 22 | */ 23 | void dump_line() 24 | { 25 | int ch; 26 | 27 | while( (ch = getchar()) != EOF && ch != '\n') 28 | /* null body*/ ; 29 | } 30 | 31 | -------------------------------------------------------------------------------- /examples/linux/asm_io.inc: -------------------------------------------------------------------------------- 1 | extern read_int, print_int, print_string 2 | extern read_char, print_char, print_nl 3 | extern sub_dump_regs, sub_dump_mem, sub_dump_math, sub_dump_stack 4 | 5 | %macro dump_regs 1 6 | push dword %1 7 | call sub_dump_regs 8 | %endmacro 9 | 10 | 11 | ; 12 | ; usage: dump_mem label, start-address, # paragraphs 13 | %macro dump_mem 3 14 | push dword %1 15 | push dword %2 16 | push dword %3 17 | call sub_dump_mem 18 | %endmacro 19 | 20 | %macro dump_math 1 21 | push dword %1 22 | call sub_dump_math 23 | %endmacro 24 | 25 | %macro dump_stack 3 26 | push dword %3 27 | push dword %2 28 | push dword %1 29 | call sub_dump_stack 30 | %endmacro -------------------------------------------------------------------------------- /examples/linux/asm_io.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/humanshell/assembly/474346d24ed2e2abb0e4edd9dc085e6b84104001/examples/linux/asm_io.o -------------------------------------------------------------------------------- /examples/linux/bitcount.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* 4 | * function bit_count 5 | * Counts the number of bits on (i.e., = 1) in an unsigned int 6 | * (This code assumes that an int is 32-bits!) 7 | * Parameter: 8 | * x - number to count bits of 9 | * Return value: 10 | * number of bits on in x 11 | */ 12 | int bit_count(unsigned int x ) 13 | { 14 | static unsigned int mask[] = { 0x55555555, 15 | 0x33333333, 16 | 0x0F0F0F0F, 17 | 0x00FF00FF, 18 | 0x0000FFFF }; 19 | int i; 20 | int shift; /* number of positions to shift to right */ 21 | 22 | for( i=0, shift=1; i < 5; i++, shift *= 2 ) 23 | x = (x & mask[i]) + ( (x >> shift) & mask[i] ); 24 | return x; 25 | } 26 | 27 | 28 | int main() 29 | { 30 | unsigned int x; 31 | 32 | printf("Enter a number: "); 33 | scanf("%i", &x); 34 | printf("There are %d bits on in %X\n", bit_count(x), x); 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /examples/linux/bitcount2.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static unsigned char byte_bit_count[256]; /* lookup table */ 4 | 5 | void initialize_count_bits() 6 | { 7 | int cnt, i, data; 8 | 9 | for( i = 0; i < 256; i++ ) { 10 | cnt = 0; 11 | data = i; 12 | while( data != 0 ) { 13 | data = data & (data - 1); 14 | cnt++; 15 | } 16 | byte_bit_count[i] = cnt; 17 | printf("%d %d\n", i, byte_bit_count[i]); 18 | } 19 | } 20 | 21 | int count_bits( unsigned int data ) 22 | { 23 | const unsigned char * dword = ( unsigned char *) & data; 24 | 25 | return byte_bit_count[dword[0]] + byte_bit_count[dword[1]] + 26 | byte_bit_count[dword[2]] + byte_bit_count[dword[3]]; 27 | } 28 | 29 | int main() 30 | { 31 | unsigned int x; 32 | 33 | initialize_count_bits(); 34 | printf("Enter a number: "); 35 | scanf("%i", &x); 36 | printf("There are %d bits on in %X\n", count_bits(x), x); 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /examples/linux/cdecl.h: -------------------------------------------------------------------------------- 1 | #ifndef CDECL_HEADER_FILE 2 | #define CDECL_HEADER_FILE 3 | 4 | /* 5 | * Define macros to specify the standard C calling convention 6 | * The macros are designed so that they will work with all 7 | * supported C/C++ compilers. 8 | * 9 | * To use define your function prototype like this: 10 | * 11 | * return_type PRE_CDECL func_name( args ) POST_CDECL; 12 | * 13 | * For example: 14 | * 15 | * int PRE_CDECL f( int x, int y) POST_CDECL; 16 | */ 17 | 18 | 19 | #if defined(__GNUC__) 20 | # define PRE_CDECL 21 | # define POST_CDECL __attribute__((cdecl)) 22 | #else 23 | # define PRE_CDECL __cdecl 24 | # define POST_CDECL 25 | #endif 26 | 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /examples/linux/dmax.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: dmax.asm 5 | 6 | global dmax 7 | 8 | 9 | 10 | segment .text 11 | ; function dmax 12 | ; returns the larger of its two double arguments 13 | ; C prototype 14 | ; double dmax( double d1, double d2 ) 15 | ; Parameters: 16 | ; d1 - first double 17 | ; d2 - second double 18 | ; Return value: 19 | ; larger of d1 and d2 (in ST0) 20 | 21 | ; next, some helpful symbols are defined 22 | 23 | %define d1 [ebp+8] 24 | %define d2 [ebp+16] 25 | 26 | dmax: 27 | enter 0, 0 28 | 29 | fld qword d2 30 | fld qword d1 ; ST0 = d1, ST1 = d2 31 | fcomip st1 ; ST0 = d2 32 | jna short d2_bigger 33 | fcomp st0 ; pop d2 from stack 34 | fld qword d1 ; ST0 = d1 35 | 36 | d2_bigger: ; if d2 is bigger, nothing to do 37 | 38 | exit: 39 | leave 40 | ret 41 | 42 | 43 | -------------------------------------------------------------------------------- /examples/linux/dmaxt.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "cdecl.h" 4 | 5 | double PRE_CDECL dmax( double, double ) POST_CDECL; 6 | 7 | int main() 8 | { 9 | double d1, d2; 10 | 11 | printf("Enter two doubles: "); 12 | scanf("%lf %lf", &d1, &d2); 13 | 14 | printf("The larger of %g and %g is %g\n", d1, d2, dmax(d1,d2)); 15 | return 0; 16 | } 17 | 18 | -------------------------------------------------------------------------------- /examples/linux/driver.c: -------------------------------------------------------------------------------- 1 | #include "cdecl.h" 2 | 3 | int PRE_CDECL asm_main( void ) POST_CDECL; 4 | 5 | int main() 6 | { 7 | int ret_status; 8 | ret_status = asm_main(); 9 | return ret_status; 10 | } 11 | -------------------------------------------------------------------------------- /examples/linux/fprime.c: -------------------------------------------------------------------------------- 1 | /* 2 | * file: fprime.c 3 | * This program calculates prime numbers 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | #include "cdecl.h" 10 | 11 | /* 12 | * function find_primes 13 | * finds the indicated number of primes 14 | * Parameters: 15 | * a - array to hold primes 16 | * n - how many primes to find 17 | */ 18 | extern void PRE_CDECL find_primes( int * a, unsigned n ) POST_CDECL; 19 | 20 | int main() 21 | { 22 | int status; 23 | unsigned i; 24 | unsigned max; 25 | int * a; 26 | 27 | printf("How many primes do you wish to find? "); 28 | scanf("%u", &max); 29 | 30 | a = calloc( sizeof(int), max); 31 | 32 | if ( a ) { 33 | 34 | find_primes(a,max); 35 | 36 | /* 37 | * print out the last 20 primes found 38 | */ 39 | for(i= ( max > 20 ) ? max - 20 : 0; i < max; i++ ) 40 | printf("%3d %d\n", i+1, a[i]); 41 | 42 | free(a); 43 | status = 0; 44 | } 45 | else { 46 | fprintf(stderr, "Can not create array of %u ints\n", max); 47 | status = 1; 48 | } 49 | 50 | return status; 51 | } 52 | -------------------------------------------------------------------------------- /examples/linux/main4.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: main4.asm 5 | ; Multi-module subprogram example program 6 | ; 7 | ; To create executable: 8 | ; Using djgpp: 9 | ; nasm -f coff sub4.asm 10 | ; nasm -f coff main4.asm 11 | ; gcc -o sub4 sub4.o main4.o driver.c asm_io.o 12 | ; 13 | ; Using Borland C/C++ 14 | ; nasm -f obj sub4.asm 15 | ; nasm -f obj main4.asm 16 | ; bcc32 sub4.obj main4.asm driver.c asm_io.obj 17 | 18 | %include "asm_io.inc" 19 | 20 | segment .data 21 | sum dd 0 22 | 23 | segment .bss 24 | input resd 1 25 | 26 | 27 | 28 | ; 29 | ; psuedo-code algorithm 30 | ; i = 1; 31 | ; sum = 0; 32 | ; while( get_int(i, &input), input != 0 ) { 33 | ; sum += input; 34 | ; i++; 35 | ; } 36 | ; print_sum(num); 37 | 38 | segment .text 39 | global asm_main 40 | extern get_int, print_sum 41 | asm_main: 42 | enter 0,0 ; setup routine 43 | pusha 44 | 45 | mov edx, 1 ; edx is 'i' in pseudo-code 46 | while_loop: 47 | push edx ; save i on stack 48 | push dword input ; push address on input on stack 49 | call get_int 50 | add esp, 8 ; remove i and &input from stack 51 | 52 | mov eax, [input] 53 | cmp eax, 0 54 | je end_while 55 | 56 | add [sum], eax ; sum += input 57 | 58 | inc edx 59 | jmp short while_loop 60 | 61 | end_while: 62 | push dword [sum] ; push value of sum onto stack 63 | call print_sum 64 | pop ecx ; remove [sum] from stack 65 | 66 | popa 67 | leave 68 | ret 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /examples/linux/main5.c: -------------------------------------------------------------------------------- 1 | /* 2 | * file: main5.c 3 | * main C program that uses assembly routine in sub5.asm 4 | * to create executable: 5 | * DJGPP: gcc -o sub5 main5.c sub5.o asm_io.o 6 | * Borland: bcc32 sub5.obj main5.c asm_io.obj 7 | */ 8 | 9 | #include 10 | 11 | #include "cdecl.h" 12 | 13 | void PRE_CDECL calc_sum( int, int * ) POST_CDECL; /* prototype for assembly routine */ 14 | 15 | int main( void ) 16 | { 17 | int n, sum; 18 | 19 | printf("Sum integers up to: "); 20 | scanf("%d", &n); 21 | calc_sum(n, &sum); 22 | printf("Sum is %d\n", sum); 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /examples/linux/main6.c: -------------------------------------------------------------------------------- 1 | /* 2 | * file: main6.c 3 | * main C program that uses assembly routine in sub5.asm 4 | * to create executable: 5 | * DJGPP: gcc -o sub5 main5.c sub5.o 6 | * Borland: bcc32 sub5.obj main5.c 7 | */ 8 | 9 | #include 10 | 11 | #include "cdecl.h" 12 | 13 | int PRE_CDECL calc_sum( int ) POST_CDECL; /* prototype for assembly routine */ 14 | 15 | int main( void ) 16 | { 17 | int n, sum; 18 | 19 | printf("Sum integers up to: "); 20 | scanf("%d", &n); 21 | sum = calc_sum(n); 22 | printf("Sum is %d\n", sum); 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /examples/linux/math.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: math.asm 5 | ; This program demonstrates how the integer multiplication and division 6 | ; instructions work. 7 | ; 8 | ; To create executable: 9 | ; nasm -f coff math.asm 10 | ; gcc -o math math.o driver.c asm_io.o 11 | 12 | %include "asm_io.inc" 13 | 14 | segment .data 15 | ; 16 | ; Output strings 17 | ; 18 | prompt db "Enter a number: ", 0 19 | square_msg db "Square of input is ", 0 20 | cube_msg db "Cube of input is ", 0 21 | cube25_msg db "Cube of input times 25 is ", 0 22 | quot_msg db "Quotient of cube/100 is ", 0 23 | rem_msg db "Remainder of cube/100 is ", 0 24 | neg_msg db "The negation of the remainder is ", 0 25 | 26 | segment .bss 27 | input resd 1 28 | 29 | 30 | segment .text 31 | global asm_main 32 | asm_main: 33 | enter 0,0 ; setup routine 34 | pusha 35 | 36 | mov eax, prompt 37 | call print_string 38 | 39 | call read_int 40 | mov [input], eax 41 | 42 | imul eax ; edx:eax = eax * eax 43 | mov ebx, eax ; save answer in ebx 44 | mov eax, square_msg 45 | call print_string 46 | mov eax, ebx 47 | call print_int 48 | call print_nl 49 | 50 | mov ebx, eax 51 | imul ebx, [input] ; ebx *= [input] 52 | mov eax, cube_msg 53 | call print_string 54 | mov eax, ebx 55 | call print_int 56 | call print_nl 57 | 58 | imul ecx, ebx, 25 ; ecx = ebx*25 59 | mov eax, cube25_msg 60 | call print_string 61 | mov eax, ecx 62 | call print_int 63 | call print_nl 64 | 65 | mov eax, ebx 66 | cdq ; initialize edx by sign extension 67 | mov ecx, 100 ; can't divide by immediate value 68 | idiv ecx ; edx:eax / ecx 69 | mov ecx, eax ; save quotient into ecx 70 | mov eax, quot_msg 71 | call print_string 72 | mov eax, ecx 73 | call print_int 74 | call print_nl 75 | mov eax, rem_msg 76 | call print_string 77 | mov eax, edx 78 | call print_int 79 | call print_nl 80 | 81 | neg edx ; negate the remainder 82 | mov eax, neg_msg 83 | call print_string 84 | mov eax, edx 85 | call print_int 86 | call print_nl 87 | 88 | popa 89 | mov eax, 0 ; return back to C 90 | leave 91 | ret 92 | 93 | 94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /examples/linux/max.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: max.asm 5 | ; This example demostrates how to avoid conditional branches 6 | 7 | %include "asm_io.inc" 8 | segment .data 9 | 10 | message1 db "Enter a number: ",0 11 | message2 db "Enter another number: ", 0 12 | message3 db "The larger number is: ", 0 13 | 14 | segment .bss 15 | 16 | input1 resd 1 ; first number entered 17 | 18 | 19 | 20 | segment .text 21 | global asm_main 22 | asm_main: 23 | enter 0,0 ; setup routine 24 | pusha 25 | 26 | mov eax, message1 ; print out first message 27 | call print_string 28 | call read_int ; input first number 29 | mov [input1], eax 30 | 31 | mov eax, message2 ; print out second message 32 | call print_string 33 | call read_int ; input second number (in eax) 34 | 35 | xor ebx, ebx ; ebx = 0 36 | cmp eax, [input1] ; compare second and first number 37 | setg bl ; ebx = (input2 > input1) ? 1 : 0 38 | neg ebx ; ebx = (input2 > input1) ? 0xFFFFFFFF : 0 39 | mov ecx, ebx ; ecx = (input2 > input1) ? 0xFFFFFFFF : 0 40 | and ecx, eax ; ecx = (input2 > input1) ? input2 : 0 41 | not ebx ; ebx = (input2 > input1) ? 0 : 0xFFFFFFFF 42 | and ebx, [input1] ; ebx = (input2 > input1) ? 0 : input1 43 | or ecx, ebx ; ecx = (input2 > input1) ? input2 : input1 44 | 45 | mov eax, message3 ; print out result 46 | call print_string 47 | mov eax, ecx 48 | call print_int 49 | call print_nl 50 | 51 | popa 52 | mov eax, 0 ; return back to C 53 | leave 54 | ret 55 | 56 | 57 | -------------------------------------------------------------------------------- /examples/linux/memex.c: -------------------------------------------------------------------------------- 1 | /* 2 | * file: memex.c 3 | */ 4 | 5 | #include 6 | 7 | #include "cdecl.h" 8 | 9 | #define STR_SIZE 30 10 | /* 11 | * prototypes 12 | */ 13 | 14 | void PRE_CDECL asm_copy( void *, 15 | const void *, 16 | unsigned ) POST_CDECL; 17 | 18 | void * PRE_CDECL asm_find( const void *, 19 | char target, 20 | unsigned ) POST_CDECL; 21 | 22 | unsigned PRE_CDECL asm_strlen( const char * ) POST_CDECL; 23 | 24 | void PRE_CDECL asm_strcpy( char *, 25 | const char * ) POST_CDECL; 26 | 27 | int main() 28 | { 29 | char st1[STR_SIZE] = "test string"; 30 | char st2[STR_SIZE]; 31 | char * st; 32 | char ch; 33 | 34 | asm_copy(st2, st1, STR_SIZE); /* copy all 30 chars of string */ 35 | printf("%s\n", st2); 36 | 37 | printf("Enter a char: "); /* look for byte in string */ 38 | scanf("%c%*[^\n]", &ch); 39 | st = asm_find(st2, ch, STR_SIZE); 40 | if ( st ) 41 | printf("Found it: %s\n", st); 42 | else 43 | printf("Not found\n"); 44 | 45 | st1[0] = 0; 46 | printf("Enter string:"); 47 | scanf("%s", st1); 48 | printf("len = %u\n", asm_strlen(st1)); 49 | 50 | asm_strcpy( st2, st1); /* copy meaningful data in string */ 51 | printf("%s\n", st2 ); 52 | 53 | return 0; 54 | } 55 | 56 | -------------------------------------------------------------------------------- /examples/linux/quadt.c: -------------------------------------------------------------------------------- 1 | /* 2 | * file: quadt.c 3 | * Test file for quad.asm 4 | */ 5 | 6 | #include 7 | 8 | #include "cdecl.h" 9 | 10 | int PRE_CDECL quadratic( double, double, double, double *, double *) POST_CDECL; 11 | 12 | int main() 13 | { 14 | double a,b,c, root1, root2; 15 | 16 | printf("Enter a, b, c: "); 17 | scanf("%lf %lf %lf", &a, &b, &c); 18 | if (quadratic( a, b, c, &root1, &root2) ) 19 | printf("roots: %.10g %.10g\n", root1, root2); 20 | else 21 | printf("No real roots\n"); 22 | return 0; 23 | } 24 | 25 | -------------------------------------------------------------------------------- /examples/linux/read.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: read.asm 5 | ; This subroutine reads an array of doubles from a file 6 | 7 | segment .data 8 | format db "%lf", 0 ; format for fscanf() 9 | 10 | segment .bss 11 | 12 | 13 | 14 | segment .text 15 | global read_doubles 16 | extern fscanf 17 | 18 | %define SIZEOF_DOUBLE 8 19 | %define FP dword [ebp + 8] 20 | %define ARRAYP dword [ebp + 12] 21 | %define ARRAY_SIZE dword [ebp + 16] 22 | %define TEMP_DOUBLE [ebp - 8] 23 | 24 | ; 25 | ; function read_doubles 26 | ; C prototype: 27 | ; int read_doubles( FILE * fp, double * arrayp, int array_size ); 28 | ; This function reads doubles from a text file into an array, until 29 | ; EOF or array is full. 30 | ; Parameters: 31 | ; fp - FILE pointer to read from (must be open for input) 32 | ; arrayp - pointer to double array to read into 33 | ; array_size - number of elements in array 34 | ; Return value: 35 | ; number of doubles stored into array (in EAX) 36 | 37 | read_doubles: 38 | push ebp 39 | mov ebp,esp 40 | sub esp, SIZEOF_DOUBLE ; define one double on stack 41 | 42 | push esi ; save esi 43 | mov esi, ARRAYP ; esi = ARRAYP 44 | xor edx, edx ; edx = array index (initially 0) 45 | 46 | while_loop: 47 | cmp edx, ARRAY_SIZE ; is edx < ARRAY_SIZE? 48 | jnl short quit ; if not, quit loop 49 | ; 50 | ; call fscanf() to read a double into TEMP_DOUBLE 51 | ; fscanf() might change edx so save it 52 | ; 53 | push edx ; save edx 54 | lea eax, TEMP_DOUBLE 55 | push eax ; push &TEMP_DOUBLE 56 | push dword format ; push &format 57 | push FP ; push file pointer 58 | call fscanf 59 | add esp, 12 60 | pop edx ; restore edx 61 | cmp eax, 1 ; did fscanf return 1? 62 | jne short quit ; if not, quit loop 63 | 64 | ; 65 | ; copy TEMP_DOUBLE into ARRAYP[edx] 66 | ; (The 8-bytes of the double are copied by two 4-byte copies) 67 | ; 68 | mov eax, [ebp - 8] 69 | mov [esi + 8*edx], eax ; first copy lowest 4 bytes 70 | mov eax, [ebp - 4] 71 | mov [esi + 8*edx + 4], eax ; next copy highest 4 bytes 72 | 73 | inc edx 74 | jmp while_loop 75 | 76 | quit: 77 | pop esi ; restore esi 78 | 79 | mov eax, edx ; store return value into eax 80 | 81 | mov esp, ebp 82 | pop ebp 83 | ret 84 | 85 | -------------------------------------------------------------------------------- /examples/linux/readt.c: -------------------------------------------------------------------------------- 1 | /* 2 | * file: readt.c 3 | * This program tests the 32-bit read_doubles() assembly procedure. 4 | * It reads the doubles from stdin. 5 | * (Use redirection to read from file.) 6 | */ 7 | 8 | #include 9 | 10 | #include "cdecl.h" 11 | 12 | extern int PRE_CDECL read_doubles( FILE *, double *, int ) POST_CDECL; 13 | 14 | #define MAX 100 15 | 16 | int main() 17 | { 18 | int i,n; 19 | double a[MAX]; 20 | 21 | n = read_doubles(stdin, a, MAX); 22 | 23 | for( i=0; i < n; i++ ) 24 | printf("%3d %g\n", i, a[i]); 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /examples/linux/skel.asm: -------------------------------------------------------------------------------- 1 | ; file: skel.asm 2 | ; 3 | ; To compile executable (linux): 4 | ; nasm -f elf skel.asm 5 | ; gcc -o skel driver.c skel.o asm_io.o 6 | 7 | %include "asm_io.inc" 8 | 9 | ; initialized data is put in the data segment 10 | segment .data 11 | 12 | ; uninitialized data is put in the bss segment 13 | segment .bss 14 | 15 | ; code is put in the text segment 16 | segment .text 17 | global asm_main 18 | asm_main: 19 | enter 0,0 ; setup routine 20 | pusha 21 | ;------------------------------------------------------------------------------ 22 | ; Do not modify the code before or after this comment. 23 | ;------------------------------------------------------------------------------ 24 | popa 25 | mov eax, 0 ; return back to C 26 | leave 27 | ret 28 | 29 | -------------------------------------------------------------------------------- /examples/linux/sub1.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: sub1.asm 5 | ; Subprogram example program 6 | ; 7 | ; To create executable: 8 | ; Using djgpp: 9 | ; nasm -f coff sub1.asm 10 | ; gcc -o sub1 sub1.o driver.c asm_io.o 11 | ; 12 | 13 | %include "asm_io.inc" 14 | 15 | segment .data 16 | prompt1 db "Enter a number: ", 0 ; don't forget nul terminator 17 | prompt2 db "Enter another number: ", 0 18 | outmsg1 db "You entered ", 0 19 | outmsg2 db " and ", 0 20 | outmsg3 db ", the sum of these is ", 0 21 | 22 | segment .bss 23 | ; 24 | ; These labels refer to double words used to store the inputs 25 | ; 26 | input1 resd 1 27 | input2 resd 1 28 | 29 | 30 | 31 | segment .text 32 | global asm_main 33 | asm_main: 34 | enter 0,0 ; setup routine 35 | pusha 36 | 37 | mov eax, prompt1 ; print out prompt 38 | call print_string 39 | 40 | mov ebx, input1 ; store address of input1 into ebx 41 | mov ecx, ret1 ; store return address into ecx 42 | jmp short get_int ; read integer 43 | ret1: 44 | mov eax, prompt2 ; print out prompt 45 | call print_string 46 | 47 | mov ebx, input2 48 | mov ecx, $ + 7 ; ecx = this address + 7 49 | jmp short get_int 50 | 51 | mov eax, [input1] ; eax = dword at input1 52 | add eax, [input2] ; eax += dword at input2 53 | mov ebx, eax ; ebx = eax 54 | ; 55 | ; next print out result message as series of steps 56 | ; 57 | 58 | mov eax, outmsg1 59 | call print_string ; print out first message 60 | mov eax, [input1] 61 | call print_int ; print out input1 62 | mov eax, outmsg2 63 | call print_string ; print out second message 64 | mov eax, [input2] 65 | call print_int ; print out input2 66 | mov eax, outmsg3 67 | call print_string ; print out third message 68 | mov eax, ebx 69 | call print_int ; print out sum (ebx) 70 | call print_nl ; print new-line 71 | 72 | popa 73 | mov eax, 0 ; return back to C 74 | leave 75 | ret 76 | ; 77 | ; subprogram get_int 78 | ; Parameters: 79 | ; ebx - address of dword to store integer into 80 | ; ecx - address of instruction to return to 81 | ; Notes: 82 | ; value of eax is destroyed 83 | get_int: 84 | call read_int 85 | mov [ebx], eax ; store input into memory 86 | jmp ecx ; jump back to caller 87 | 88 | 89 | -------------------------------------------------------------------------------- /examples/linux/sub2.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: sub2.asm 5 | ; Subprogram example program 6 | ; 7 | ; To create executable: 8 | ; Using djgpp: 9 | ; nasm -f coff sub2.asm 10 | ; gcc -o sub1 sub2.o driver.c asm_io.o 11 | ; 12 | ; Using Borland C/C++ 13 | ; nasm -f obj sub2.asm 14 | ; bcc32 sub2.obj driver.c asm_io.obj 15 | 16 | %include "asm_io.inc" 17 | 18 | segment .data 19 | prompt1 db "Enter a number: ", 0 ; don't forget nul terminator 20 | prompt2 db "Enter another number: ", 0 21 | outmsg1 db "You entered ", 0 22 | outmsg2 db " and ", 0 23 | outmsg3 db ", the sum of these is ", 0 24 | 25 | segment .bss 26 | ; 27 | ; These labels refer to double words used to store the inputs 28 | ; 29 | input1 resd 1 30 | input2 resd 1 31 | 32 | 33 | 34 | segment .text 35 | global asm_main 36 | asm_main: 37 | enter 0,0 ; setup routine 38 | pusha 39 | 40 | mov eax, prompt1 ; print out prompt 41 | call print_string 42 | 43 | mov ebx, input1 ; store address of input1 into ebx 44 | call get_int ; read integer 45 | 46 | mov eax, prompt2 ; print out prompt 47 | call print_string 48 | 49 | mov ebx, input2 50 | call get_int 51 | 52 | mov eax, [input1] ; eax = dword at input1 53 | add eax, [input2] ; eax += dword at input2 54 | mov ebx, eax ; ebx = eax 55 | ; 56 | ; next print out result message as series of steps 57 | ; 58 | 59 | mov eax, outmsg1 60 | call print_string ; print out first message 61 | mov eax, [input1] 62 | call print_int ; print out input1 63 | mov eax, outmsg2 64 | call print_string ; print out second message 65 | mov eax, [input2] 66 | call print_int ; print out input2 67 | mov eax, outmsg3 68 | call print_string ; print out third message 69 | mov eax, ebx 70 | call print_int ; print out sum (ebx) 71 | call print_nl ; print new-line 72 | 73 | popa 74 | mov eax, 0 ; return back to C 75 | leave 76 | ret 77 | ; 78 | ; subprogram get_int 79 | ; Parameters: 80 | ; ebx - address of word to store integer into 81 | ; Notes: 82 | ; value of eax is destroyed 83 | get_int: 84 | call read_int 85 | mov [ebx], eax ; store input into memory 86 | ret ; jump back to caller 87 | 88 | 89 | -------------------------------------------------------------------------------- /examples/linux/sub4.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: sub4.asm 5 | ; Subprogram example 6 | 7 | %include "asm_io.inc" 8 | 9 | ; 10 | ; subprogram get_int 11 | ; Parameters (in order pushed on stack) 12 | ; number of input (at [ebp + 12]) 13 | ; address of word to store input into (at [ebp + 8]) 14 | ; Notes: 15 | ; values of eax and ebx are destroyed 16 | segment .data 17 | prompt db ") Enter an integer number (0 to quit): ", 0 18 | 19 | segment .bss 20 | 21 | 22 | 23 | segment .text 24 | global get_int, print_sum 25 | get_int: 26 | enter 0,0 27 | 28 | mov eax, [ebp + 12] 29 | call print_int 30 | 31 | mov eax, prompt 32 | call print_string 33 | 34 | call read_int 35 | mov ebx, [ebp + 8] 36 | mov [ebx], eax ; store input into memory 37 | 38 | leave 39 | ret ; jump back to caller 40 | 41 | ; subprogram print_sum 42 | ; prints out the sum 43 | ; Parameter: 44 | ; sum to print out (at [ebp+8]) 45 | ; Note: destroys value of eax 46 | ; 47 | segment .data 48 | result db "The sum is ", 0 49 | 50 | segment .text 51 | print_sum: 52 | enter 0,0 53 | 54 | mov eax, result 55 | call print_string 56 | 57 | mov eax, [ebp+8] 58 | call print_int 59 | call print_nl 60 | 61 | leave 62 | ret 63 | 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /examples/linux/sub5.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: sub5.asm 5 | ; Subprogram to C interfacing example 6 | 7 | %include "asm_io.inc" 8 | 9 | ; subroutine calc_sum 10 | ; finds the sum of the integers 1 through n 11 | ; Parameters: 12 | ; n - what to sum up to (at [ebp + 8]) 13 | ; sump - pointer to int to store sum into (at [ebp + 12]) 14 | ; pseudo C code: 15 | ; void calc_sum( int n, int * sump ) 16 | ; { 17 | ; int i, sum = 0; 18 | ; for( i=1; i <= n; i++ ) 19 | ; sum += i; 20 | ; *sump = sum; 21 | ; } 22 | ; 23 | ; To assemble: 24 | ; DJGPP: nasm -f coff sub5.asm 25 | ; Borland: nasm -f obj sub5.asm 26 | 27 | segment .text 28 | global calc_sum 29 | ; 30 | ; local variable: 31 | ; sum at [ebp-4] 32 | calc_sum: 33 | enter 4,0 ; allocate room for sum on stack 34 | push ebx ; IMPORTANT! 35 | 36 | mov dword [ebp-4],0 ; sum = 0 37 | dump_stack 1, 2, 4 ; print out stack from ebp-8 to ebp+16 38 | mov ecx, 1 ; ecx is i in pseudocode 39 | for_loop: 40 | cmp ecx, [ebp+8] ; cmp i and n 41 | jnle end_for ; if not i <= n, quit 42 | 43 | add [ebp-4], ecx ; sum += i 44 | inc ecx 45 | jmp short for_loop 46 | 47 | end_for: 48 | mov ebx, [ebp+12] ; ebx = sump 49 | mov eax, [ebp-4] ; eax = sum 50 | mov [ebx], eax 51 | 52 | pop ebx ; restore ebx 53 | leave 54 | ret 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /examples/linux/sub6.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: sub6.asm 5 | ; Subprogram to C interfacing example 6 | 7 | ; subroutine calc_sum 8 | ; finds the sum of the integers 1 through n 9 | ; Parameters: 10 | ; n - what to sum up to (at [ebp + 8]) 11 | ; Return value: 12 | ; value of sum 13 | ; pseudo C code: 14 | ; int calc_sum( int n ) 15 | ; { 16 | ; int i, sum = 0; 17 | ; for( i=1; i <= n; i++ ) 18 | ; sum += i; 19 | ; return sum; 20 | ; } 21 | ; 22 | ; To assemble: 23 | ; DJGPP: nasm -f coff sub6.asm 24 | ; Borland: nasm -f obj sub6.asm 25 | 26 | segment .text 27 | global calc_sum 28 | ; 29 | ; local variable: 30 | ; sum at [ebp-4] 31 | calc_sum: 32 | enter 4,0 ; make room for sum on stack 33 | 34 | mov dword [ebp-4],0 ; sum = 0 35 | mov ecx, 1 ; ecx is i in pseudocode 36 | for_loop: 37 | cmp ecx, [ebp+8] ; cmp i and n 38 | jnle end_for ; if not i <= n, quit 39 | 40 | add [ebp-4], ecx ; sum += i 41 | inc ecx 42 | jmp short for_loop 43 | 44 | end_for: 45 | mov eax, [ebp-4] ; eax = sum 46 | 47 | leave 48 | ret 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /examples/linux/test_big_int.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * file: big_int_test.cpp 3 | * A small test program for the Big_int class 4 | */ 5 | #include "big_int.hpp" 6 | #include 7 | 8 | // Borland (or at least bcc32 ver 5.2) doesn't support the std namespace 9 | #if ! ( ( defined(__BORLANDC__) && __BORLANDC__ < 0x550 ) || defined(__WATCOMC__) ) 10 | using namespace std; 11 | #endif 12 | 13 | int main() 14 | { 15 | try { 16 | // 12345678901234567890 17 | Big_int b(5,"8000000000000a00b"); 18 | Big_int a(5,"80000000000010230"); 19 | Big_int c = a + b; 20 | cout << a << " + " << b << " = " << c << endl; 21 | for( int i=0; i < 2; i++ ) { 22 | c = c + a; 23 | cout << "c = " << c << endl; 24 | } 25 | cout << "c-1 = " << c - Big_int(5,1) << endl; 26 | Big_int d(5, "12345678"); 27 | cout << "d = " << d << endl; 28 | cout << "c == d " << (c == d) << endl; 29 | cout << "c > d " << (c > d) << endl; 30 | } 31 | catch( const char * str ) { 32 | cerr << "Caught: " << str << endl; 33 | } 34 | catch( Big_int::Overflow ) { 35 | cerr << "Overflow" << endl; 36 | } 37 | catch( Big_int::Size_mismatch ) { 38 | cerr << "Size mismatch" << endl; 39 | } 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /examples/ms-ex.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/humanshell/assembly/474346d24ed2e2abb0e4edd9dc085e6b84104001/examples/ms-ex.zip -------------------------------------------------------------------------------- /examples/ms/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Microsoft makefile 3 | # Use with nmake 4 | # 5 | 6 | .SUFFIXES: 7 | .SUFFIXES: .obj .asm .cpp .c 8 | 9 | AS=nasm 10 | ASFLAGS= -f win32 11 | CFLAGS= 12 | CC=cl 13 | CXX=cl 14 | CXXFLAGS=-GX 15 | 16 | .asm.obj: 17 | $(AS) $(ASFLAGS) $*.asm 18 | 19 | .cpp.obj: 20 | $(CXX) -c $(CXXFLAGS) $*.cpp 21 | 22 | .c.obj: 23 | $(CC) -c $(CFLAGS) $*.c 24 | 25 | all: prime.exe math.exe sub1.exe sub2.exe sub3.exe sub4.exe sub5.exe sub6.exe first.exe memex.exe dmaxt.exe asm_io.obj fprime.exe quadt.exe test_big_int.exe 26 | 27 | prime.exe: driver.obj prime.obj asm_io.obj 28 | $(CC) $(CFLAGS) -Feprime.exe driver.obj prime.obj asm_io.obj 29 | 30 | math.exe : driver.obj math.obj asm_io.obj 31 | $(CC) $(CFLAGS) -Femath.exe driver.obj math.obj asm_io.obj 32 | 33 | first.exe : driver.obj first.obj asm_io.obj 34 | $(CC) $(CFLAGS) -Fefirst.exe driver.obj first.obj asm_io.obj 35 | 36 | sub1.exe : driver.obj sub1.obj asm_io.obj 37 | $(CC) $(CFLAGS) -Fesub1.exe driver.obj sub1.obj asm_io.obj 38 | 39 | sub2.exe : driver.obj sub2.obj asm_io.obj 40 | $(CC) $(CFLAGS) -Fesub2.exe driver.obj sub2.obj asm_io.obj 41 | 42 | sub3.exe : driver.obj sub3.obj asm_io.obj 43 | $(CC) $(CFLAGS) -Fesub3.exe driver.obj sub3.obj asm_io.obj 44 | 45 | sub4.exe : driver.obj sub4.obj main4.obj asm_io.obj 46 | $(CC) $(CFLAGS) -Fesub4.exe driver.obj sub4.obj main4.obj asm_io.obj 47 | 48 | sub5.exe : main5.obj sub5.obj asm_io.obj 49 | $(CC) $(CFLAGS) -Fesub5.exe main5.obj sub5.obj asm_io.obj 50 | 51 | sub6.exe : main6.obj sub6.obj 52 | $(CC) $(CFLAGS) -Fesub6.exe main6.obj sub6.obj 53 | 54 | asm_io.obj : asm_io.asm 55 | $(AS) $(ASFLAGS) -d COFF_TYPE asm_io.asm 56 | 57 | array1.exe : driver.obj array1.obj array1c.obj 58 | $(CC) $(CFLAGS) -Fearray1.exe array1.obj array1c.obj asm_io.obj 59 | 60 | memex.exe : memex.obj memory.obj 61 | $(CC) $(CFLAGS) -Fememex.exe memex.obj memory.obj 62 | 63 | dmaxt.exe : dmaxt.obj dmax.obj 64 | $(CC) $(CFLAGS) -Fedmaxt.exe dmaxt.obj dmax.obj 65 | 66 | quadt.exe : quadt.obj quad.obj 67 | $(CC) $(CFLAGS) -Fequadt.exe quadt.obj quad.obj 68 | 69 | readt.exe : readt.obj read.obj 70 | $(CC) $(CFLAGS) -Fereadt.exe readt.obj read.obj 71 | 72 | fprime.exe : fprime.obj prime2.obj 73 | $(CC) $(CFLAGS) -Fefprime.exe fprime.obj prime2.obj 74 | 75 | test_big_int.exe : test_big_int.obj big_int.obj big_math.obj 76 | $(CXX) $(CXXFLAGS) -Fetest_big_int.exe test_big_int.obj big_int.obj big_math.obj 77 | 78 | big_int.obj : big_int.hpp big_int.cpp 79 | 80 | test_big_int.obj : big_int.hpp test_big_int.cpp 81 | 82 | first.obj : asm_io.inc first.asm 83 | 84 | sub1.obj : asm_io.inc 85 | 86 | sub2.obj : asm_io.inc 87 | 88 | sub3.obj : asm_io.inc 89 | 90 | sub4.obj : asm_io.inc 91 | 92 | main4.obj : asm_io.inc 93 | 94 | driver.obj : driver.c 95 | 96 | 97 | clean : 98 | del *.obj -------------------------------------------------------------------------------- /examples/ms/array1c.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Driver file for array1.asm file 3 | */ 4 | 5 | #include 6 | 7 | #include "cdecl.h" 8 | 9 | int PRE_CDECL asm_main( void ) POST_CDECL; 10 | void PRE_CDECL dump_line( void ) POST_CDECL; 11 | 12 | int main() 13 | { 14 | int ret_status; 15 | ret_status = asm_main(); 16 | return ret_status; 17 | } 18 | 19 | /* 20 | * function dump_line 21 | * dumps all chars left in current line from input buffer 22 | */ 23 | void dump_line() 24 | { 25 | int ch; 26 | 27 | while( (ch = getchar()) != EOF && ch != '\n') 28 | /* null body*/ ; 29 | } 30 | 31 | -------------------------------------------------------------------------------- /examples/ms/asm_io.inc: -------------------------------------------------------------------------------- 1 | extern read_int, print_int, print_string 2 | extern read_char, print_char, print_nl 3 | extern sub_dump_regs, sub_dump_mem, sub_dump_math, sub_dump_stack 4 | 5 | %macro dump_regs 1 6 | push dword %1 7 | call sub_dump_regs 8 | %endmacro 9 | 10 | 11 | ; 12 | ; usage: dump_mem label, start-address, # paragraphs 13 | %macro dump_mem 3 14 | push dword %1 15 | push dword %2 16 | push dword %3 17 | call sub_dump_mem 18 | %endmacro 19 | 20 | %macro dump_math 1 21 | push dword %1 22 | call sub_dump_math 23 | %endmacro 24 | 25 | %macro dump_stack 3 26 | push dword %3 27 | push dword %2 28 | push dword %1 29 | call sub_dump_stack 30 | %endmacro -------------------------------------------------------------------------------- /examples/ms/asm_io.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/humanshell/assembly/474346d24ed2e2abb0e4edd9dc085e6b84104001/examples/ms/asm_io.obj -------------------------------------------------------------------------------- /examples/ms/bitcount.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* 4 | * function bit_count 5 | * Counts the number of bits on (i.e., = 1) in an unsigned int 6 | * (This code assumes that an int is 32-bits!) 7 | * Parameter: 8 | * x - number to count bits of 9 | * Return value: 10 | * number of bits on in x 11 | */ 12 | int bit_count(unsigned int x ) 13 | { 14 | static unsigned int mask[] = { 0x55555555, 15 | 0x33333333, 16 | 0x0F0F0F0F, 17 | 0x00FF00FF, 18 | 0x0000FFFF }; 19 | int i; 20 | int shift; /* number of positions to shift to right */ 21 | 22 | for( i=0, shift=1; i < 5; i++, shift *= 2 ) 23 | x = (x & mask[i]) + ( (x >> shift) & mask[i] ); 24 | return x; 25 | } 26 | 27 | 28 | int main() 29 | { 30 | unsigned int x; 31 | 32 | printf("Enter a number: "); 33 | scanf("%i", &x); 34 | printf("There are %d bits on in %X\n", bit_count(x), x); 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /examples/ms/bitcount2.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static unsigned char byte_bit_count[256]; /* lookup table */ 4 | 5 | void initialize_count_bits() 6 | { 7 | int cnt, i, data; 8 | 9 | for( i = 0; i < 256; i++ ) { 10 | cnt = 0; 11 | data = i; 12 | while( data != 0 ) { 13 | data = data & (data - 1); 14 | cnt++; 15 | } 16 | byte_bit_count[i] = cnt; 17 | printf("%d %d\n", i, byte_bit_count[i]); 18 | } 19 | } 20 | 21 | int count_bits( unsigned int data ) 22 | { 23 | const unsigned char * dword = ( unsigned char *) & data; 24 | 25 | return byte_bit_count[dword[0]] + byte_bit_count[dword[1]] + 26 | byte_bit_count[dword[2]] + byte_bit_count[dword[3]]; 27 | } 28 | 29 | int main() 30 | { 31 | unsigned int x; 32 | 33 | initialize_count_bits(); 34 | printf("Enter a number: "); 35 | scanf("%i", &x); 36 | printf("There are %d bits on in %X\n", count_bits(x), x); 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /examples/ms/cdecl.h: -------------------------------------------------------------------------------- 1 | #ifndef CDECL_HEADER_FILE 2 | #define CDECL_HEADER_FILE 3 | 4 | /* 5 | * Define macros to specify the standard C calling convention 6 | * The macros are designed so that they will work with all 7 | * supported C/C++ compilers. 8 | * 9 | * To use define your function prototype like this: 10 | * 11 | * return_type PRE_CDECL func_name( args ) POST_CDECL; 12 | * 13 | * For example: 14 | * 15 | * int PRE_CDECL f( int x, int y) POST_CDECL; 16 | */ 17 | 18 | 19 | #if defined(__GNUC__) 20 | # define PRE_CDECL 21 | # define POST_CDECL __attribute__((cdecl)) 22 | #else 23 | # define PRE_CDECL __cdecl 24 | # define POST_CDECL 25 | #endif 26 | 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /examples/ms/dmax.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: dmax.asm 5 | 6 | global _dmax 7 | 8 | 9 | 10 | segment .text 11 | ; function _dmax 12 | ; returns the larger of its two double arguments 13 | ; C prototype 14 | ; double dmax( double d1, double d2 ) 15 | ; Parameters: 16 | ; d1 - first double 17 | ; d2 - second double 18 | ; Return value: 19 | ; larger of d1 and d2 (in ST0) 20 | 21 | ; next, some helpful symbols are defined 22 | 23 | %define d1 [ebp+8] 24 | %define d2 [ebp+16] 25 | 26 | _dmax: 27 | enter 0, 0 28 | 29 | fld qword d2 30 | fld qword d1 ; ST0 = d1, ST1 = d2 31 | fcomip st1 ; ST0 = d2 32 | jna short d2_bigger 33 | fcomp st0 ; pop d2 from stack 34 | fld qword d1 ; ST0 = d1 35 | 36 | d2_bigger: ; if d2 is bigger, nothing to do 37 | 38 | exit: 39 | leave 40 | ret 41 | 42 | 43 | -------------------------------------------------------------------------------- /examples/ms/dmaxt.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "cdecl.h" 4 | 5 | double PRE_CDECL dmax( double, double ) POST_CDECL; 6 | 7 | int main() 8 | { 9 | double d1, d2; 10 | 11 | printf("Enter two doubles: "); 12 | scanf("%lf %lf", &d1, &d2); 13 | 14 | printf("The larger of %g and %g is %g\n", d1, d2, dmax(d1,d2)); 15 | return 0; 16 | } 17 | 18 | -------------------------------------------------------------------------------- /examples/ms/driver.c: -------------------------------------------------------------------------------- 1 | #include "cdecl.h" 2 | 3 | int PRE_CDECL asm_main( void ) POST_CDECL; 4 | 5 | int main() 6 | { 7 | int ret_status; 8 | ret_status = asm_main(); 9 | return ret_status; 10 | } 11 | -------------------------------------------------------------------------------- /examples/ms/fprime.c: -------------------------------------------------------------------------------- 1 | /* 2 | * file: fprime.c 3 | * This program calculates prime numbers 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | #include "cdecl.h" 10 | 11 | /* 12 | * function find_primes 13 | * finds the indicated number of primes 14 | * Parameters: 15 | * a - array to hold primes 16 | * n - how many primes to find 17 | */ 18 | extern void PRE_CDECL find_primes( int * a, unsigned n ) POST_CDECL; 19 | 20 | int main() 21 | { 22 | int status; 23 | unsigned i; 24 | unsigned max; 25 | int * a; 26 | 27 | printf("How many primes do you wish to find? "); 28 | scanf("%u", &max); 29 | 30 | a = calloc( sizeof(int), max); 31 | 32 | if ( a ) { 33 | 34 | find_primes(a,max); 35 | 36 | /* 37 | * print out the last 20 primes found 38 | */ 39 | for(i= ( max > 20 ) ? max - 20 : 0; i < max; i++ ) 40 | printf("%3d %d\n", i+1, a[i]); 41 | 42 | free(a); 43 | status = 0; 44 | } 45 | else { 46 | fprintf(stderr, "Can not create array of %u ints\n", max); 47 | status = 1; 48 | } 49 | 50 | return status; 51 | } 52 | -------------------------------------------------------------------------------- /examples/ms/main4.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: main4.asm 5 | ; Multi-module subprogram example program 6 | ; 7 | ; To create executable: 8 | ; Using djgpp: 9 | ; nasm -f coff sub4.asm 10 | ; nasm -f coff main4.asm 11 | ; gcc -o sub4 sub4.o main4.o driver.c asm_io.o 12 | ; 13 | ; Using Borland C/C++ 14 | ; nasm -f obj sub4.asm 15 | ; nasm -f obj main4.asm 16 | ; bcc32 sub4.obj main4.asm driver.c asm_io.obj 17 | 18 | %include "asm_io.inc" 19 | 20 | segment .data 21 | sum dd 0 22 | 23 | segment .bss 24 | input resd 1 25 | 26 | 27 | 28 | ; 29 | ; psuedo-code algorithm 30 | ; i = 1; 31 | ; sum = 0; 32 | ; while( get_int(i, &input), input != 0 ) { 33 | ; sum += input; 34 | ; i++; 35 | ; } 36 | ; print_sum(num); 37 | 38 | segment .text 39 | global _asm_main 40 | extern get_int, print_sum 41 | _asm_main: 42 | enter 0,0 ; setup routine 43 | pusha 44 | 45 | mov edx, 1 ; edx is 'i' in pseudo-code 46 | while_loop: 47 | push edx ; save i on stack 48 | push dword input ; push address on input on stack 49 | call get_int 50 | add esp, 8 ; remove i and &input from stack 51 | 52 | mov eax, [input] 53 | cmp eax, 0 54 | je end_while 55 | 56 | add [sum], eax ; sum += input 57 | 58 | inc edx 59 | jmp short while_loop 60 | 61 | end_while: 62 | push dword [sum] ; push value of sum onto stack 63 | call print_sum 64 | pop ecx ; remove [sum] from stack 65 | 66 | popa 67 | leave 68 | ret 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /examples/ms/main5.c: -------------------------------------------------------------------------------- 1 | /* 2 | * file: main5.c 3 | * main C program that uses assembly routine in sub5.asm 4 | * to create executable: 5 | * DJGPP: gcc -o sub5 main5.c sub5.o asm_io.o 6 | * Borland: bcc32 sub5.obj main5.c asm_io.obj 7 | */ 8 | 9 | #include 10 | 11 | #include "cdecl.h" 12 | 13 | void PRE_CDECL calc_sum( int, int * ) POST_CDECL; /* prototype for assembly routine */ 14 | 15 | int main( void ) 16 | { 17 | int n, sum; 18 | 19 | printf("Sum integers up to: "); 20 | scanf("%d", &n); 21 | calc_sum(n, &sum); 22 | printf("Sum is %d\n", sum); 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /examples/ms/main6.c: -------------------------------------------------------------------------------- 1 | /* 2 | * file: main6.c 3 | * main C program that uses assembly routine in sub5.asm 4 | * to create executable: 5 | * DJGPP: gcc -o sub5 main5.c sub5.o 6 | * Borland: bcc32 sub5.obj main5.c 7 | */ 8 | 9 | #include 10 | 11 | #include "cdecl.h" 12 | 13 | int PRE_CDECL calc_sum( int ) POST_CDECL; /* prototype for assembly routine */ 14 | 15 | int main( void ) 16 | { 17 | int n, sum; 18 | 19 | printf("Sum integers up to: "); 20 | scanf("%d", &n); 21 | sum = calc_sum(n); 22 | printf("Sum is %d\n", sum); 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /examples/ms/math.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: math.asm 5 | ; This program demonstrates how the integer multiplication and division 6 | ; instructions work. 7 | ; 8 | ; To create executable: 9 | ; nasm -f coff math.asm 10 | ; gcc -o math math.o driver.c asm_io.o 11 | 12 | %include "asm_io.inc" 13 | 14 | segment .data 15 | ; 16 | ; Output strings 17 | ; 18 | prompt db "Enter a number: ", 0 19 | square_msg db "Square of input is ", 0 20 | cube_msg db "Cube of input is ", 0 21 | cube25_msg db "Cube of input times 25 is ", 0 22 | quot_msg db "Quotient of cube/100 is ", 0 23 | rem_msg db "Remainder of cube/100 is ", 0 24 | neg_msg db "The negation of the remainder is ", 0 25 | 26 | segment .bss 27 | input resd 1 28 | 29 | 30 | segment .text 31 | global _asm_main 32 | _asm_main: 33 | enter 0,0 ; setup routine 34 | pusha 35 | 36 | mov eax, prompt 37 | call print_string 38 | 39 | call read_int 40 | mov [input], eax 41 | 42 | imul eax ; edx:eax = eax * eax 43 | mov ebx, eax ; save answer in ebx 44 | mov eax, square_msg 45 | call print_string 46 | mov eax, ebx 47 | call print_int 48 | call print_nl 49 | 50 | mov ebx, eax 51 | imul ebx, [input] ; ebx *= [input] 52 | mov eax, cube_msg 53 | call print_string 54 | mov eax, ebx 55 | call print_int 56 | call print_nl 57 | 58 | imul ecx, ebx, 25 ; ecx = ebx*25 59 | mov eax, cube25_msg 60 | call print_string 61 | mov eax, ecx 62 | call print_int 63 | call print_nl 64 | 65 | mov eax, ebx 66 | cdq ; initialize edx by sign extension 67 | mov ecx, 100 ; can't divide by immediate value 68 | idiv ecx ; edx:eax / ecx 69 | mov ecx, eax ; save quotient into ecx 70 | mov eax, quot_msg 71 | call print_string 72 | mov eax, ecx 73 | call print_int 74 | call print_nl 75 | mov eax, rem_msg 76 | call print_string 77 | mov eax, edx 78 | call print_int 79 | call print_nl 80 | 81 | neg edx ; negate the remainder 82 | mov eax, neg_msg 83 | call print_string 84 | mov eax, edx 85 | call print_int 86 | call print_nl 87 | 88 | popa 89 | mov eax, 0 ; return back to C 90 | leave 91 | ret 92 | 93 | 94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /examples/ms/max.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: max.asm 5 | ; This example demostrates how to avoid conditional branches 6 | 7 | %include "asm_io.inc" 8 | segment .data 9 | 10 | message1 db "Enter a number: ",0 11 | message2 db "Enter another number: ", 0 12 | message3 db "The larger number is: ", 0 13 | 14 | segment .bss 15 | 16 | input1 resd 1 ; first number entered 17 | 18 | 19 | 20 | segment .text 21 | global _asm_main 22 | _asm_main: 23 | enter 0,0 ; setup routine 24 | pusha 25 | 26 | mov eax, message1 ; print out first message 27 | call print_string 28 | call read_int ; input first number 29 | mov [input1], eax 30 | 31 | mov eax, message2 ; print out second message 32 | call print_string 33 | call read_int ; input second number (in eax) 34 | 35 | xor ebx, ebx ; ebx = 0 36 | cmp eax, [input1] ; compare second and first number 37 | setg bl ; ebx = (input2 > input1) ? 1 : 0 38 | neg ebx ; ebx = (input2 > input1) ? 0xFFFFFFFF : 0 39 | mov ecx, ebx ; ecx = (input2 > input1) ? 0xFFFFFFFF : 0 40 | and ecx, eax ; ecx = (input2 > input1) ? input2 : 0 41 | not ebx ; ebx = (input2 > input1) ? 0 : 0xFFFFFFFF 42 | and ebx, [input1] ; ebx = (input2 > input1) ? 0 : input1 43 | or ecx, ebx ; ecx = (input2 > input1) ? input2 : input1 44 | 45 | mov eax, message3 ; print out result 46 | call print_string 47 | mov eax, ecx 48 | call print_int 49 | call print_nl 50 | 51 | popa 52 | mov eax, 0 ; return back to C 53 | leave 54 | ret 55 | 56 | 57 | -------------------------------------------------------------------------------- /examples/ms/memex.c: -------------------------------------------------------------------------------- 1 | /* 2 | * file: memex.c 3 | */ 4 | 5 | #include 6 | 7 | #include "cdecl.h" 8 | 9 | #define STR_SIZE 30 10 | /* 11 | * prototypes 12 | */ 13 | 14 | void PRE_CDECL asm_copy( void *, 15 | const void *, 16 | unsigned ) POST_CDECL; 17 | 18 | void * PRE_CDECL asm_find( const void *, 19 | char target, 20 | unsigned ) POST_CDECL; 21 | 22 | unsigned PRE_CDECL asm_strlen( const char * ) POST_CDECL; 23 | 24 | void PRE_CDECL asm_strcpy( char *, 25 | const char * ) POST_CDECL; 26 | 27 | int main() 28 | { 29 | char st1[STR_SIZE] = "test string"; 30 | char st2[STR_SIZE]; 31 | char * st; 32 | char ch; 33 | 34 | asm_copy(st2, st1, STR_SIZE); /* copy all 30 chars of string */ 35 | printf("%s\n", st2); 36 | 37 | printf("Enter a char: "); /* look for byte in string */ 38 | scanf("%c%*[^\n]", &ch); 39 | st = asm_find(st2, ch, STR_SIZE); 40 | if ( st ) 41 | printf("Found it: %s\n", st); 42 | else 43 | printf("Not found\n"); 44 | 45 | st1[0] = 0; 46 | printf("Enter string:"); 47 | scanf("%s", st1); 48 | printf("len = %u\n", asm_strlen(st1)); 49 | 50 | asm_strcpy( st2, st1); /* copy meaningful data in string */ 51 | printf("%s\n", st2 ); 52 | 53 | return 0; 54 | } 55 | 56 | -------------------------------------------------------------------------------- /examples/ms/quadt.c: -------------------------------------------------------------------------------- 1 | /* 2 | * file: quadt.c 3 | * Test file for quad.asm 4 | */ 5 | 6 | #include 7 | 8 | #include "cdecl.h" 9 | 10 | int PRE_CDECL quadratic( double, double, double, double *, double *) POST_CDECL; 11 | 12 | int main() 13 | { 14 | double a,b,c, root1, root2; 15 | 16 | printf("Enter a, b, c: "); 17 | scanf("%lf %lf %lf", &a, &b, &c); 18 | if (quadratic( a, b, c, &root1, &root2) ) 19 | printf("roots: %.10g %.10g\n", root1, root2); 20 | else 21 | printf("No real roots\n"); 22 | return 0; 23 | } 24 | 25 | -------------------------------------------------------------------------------- /examples/ms/read.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: read.asm 5 | ; This subroutine reads an array of doubles from a file 6 | 7 | segment .data 8 | format db "%lf", 0 ; format for fscanf() 9 | 10 | segment .bss 11 | 12 | 13 | 14 | segment .text 15 | global _read_doubles 16 | extern _fscanf 17 | 18 | %define SIZEOF_DOUBLE 8 19 | %define FP dword [ebp + 8] 20 | %define ARRAYP dword [ebp + 12] 21 | %define ARRAY_SIZE dword [ebp + 16] 22 | %define TEMP_DOUBLE [ebp - 8] 23 | 24 | ; 25 | ; function _read_doubles 26 | ; C prototype: 27 | ; int read_doubles( FILE * fp, double * arrayp, int array_size ); 28 | ; This function reads doubles from a text file into an array, until 29 | ; EOF or array is full. 30 | ; Parameters: 31 | ; fp - FILE pointer to read from (must be open for input) 32 | ; arrayp - pointer to double array to read into 33 | ; array_size - number of elements in array 34 | ; Return value: 35 | ; number of doubles stored into array (in EAX) 36 | 37 | _read_doubles: 38 | push ebp 39 | mov ebp,esp 40 | sub esp, SIZEOF_DOUBLE ; define one double on stack 41 | 42 | push esi ; save esi 43 | mov esi, ARRAYP ; esi = ARRAYP 44 | xor edx, edx ; edx = array index (initially 0) 45 | 46 | while_loop: 47 | cmp edx, ARRAY_SIZE ; is edx < ARRAY_SIZE? 48 | jnl short quit ; if not, quit loop 49 | ; 50 | ; call fscanf() to read a double into TEMP_DOUBLE 51 | ; fscanf() might change edx so save it 52 | ; 53 | push edx ; save edx 54 | lea eax, TEMP_DOUBLE 55 | push eax ; push &TEMP_DOUBLE 56 | push dword format ; push &format 57 | push FP ; push file pointer 58 | call _fscanf 59 | add esp, 12 60 | pop edx ; restore edx 61 | cmp eax, 1 ; did fscanf return 1? 62 | jne short quit ; if not, quit loop 63 | 64 | ; 65 | ; copy TEMP_DOUBLE into ARRAYP[edx] 66 | ; (The 8-bytes of the double are copied by two 4-byte copies) 67 | ; 68 | mov eax, [ebp - 8] 69 | mov [esi + 8*edx], eax ; first copy lowest 4 bytes 70 | mov eax, [ebp - 4] 71 | mov [esi + 8*edx + 4], eax ; next copy highest 4 bytes 72 | 73 | inc edx 74 | jmp while_loop 75 | 76 | quit: 77 | pop esi ; restore esi 78 | 79 | mov eax, edx ; store return value into eax 80 | 81 | mov esp, ebp 82 | pop ebp 83 | ret 84 | 85 | -------------------------------------------------------------------------------- /examples/ms/readt.c: -------------------------------------------------------------------------------- 1 | /* 2 | * file: readt.c 3 | * This program tests the 32-bit read_doubles() assembly procedure. 4 | * It reads the doubles from stdin. 5 | * (Use redirection to read from file.) 6 | */ 7 | 8 | #include 9 | 10 | #include "cdecl.h" 11 | 12 | extern int PRE_CDECL read_doubles( FILE *, double *, int ) POST_CDECL; 13 | 14 | #define MAX 100 15 | 16 | int main() 17 | { 18 | int i,n; 19 | double a[MAX]; 20 | 21 | n = read_doubles(stdin, a, MAX); 22 | 23 | for( i=0; i < n; i++ ) 24 | printf("%3d %g\n", i, a[i]); 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /examples/ms/skel.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: skel.asm 5 | ; This file is a skeleton that can be used to start assembly programs. 6 | 7 | %include "asm_io.inc" 8 | segment .data 9 | ; 10 | ; initialized data is put in the data segment here 11 | ; 12 | 13 | 14 | segment .bss 15 | ; 16 | ; uninitialized data is put in the bss segment 17 | ; 18 | 19 | 20 | 21 | 22 | segment .text 23 | global _asm_main 24 | _asm_main: 25 | enter 0,0 ; setup routine 26 | pusha 27 | 28 | ; 29 | ; code is put in the text segment. Do not modify the code before 30 | ; or after this comment. 31 | ; 32 | 33 | popa 34 | mov eax, 0 ; return back to C 35 | leave 36 | ret 37 | 38 | 39 | -------------------------------------------------------------------------------- /examples/ms/sub1.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: sub1.asm 5 | ; Subprogram example program 6 | ; 7 | ; To create executable: 8 | ; Using djgpp: 9 | ; nasm -f coff sub1.asm 10 | ; gcc -o sub1 sub1.o driver.c asm_io.o 11 | ; 12 | 13 | %include "asm_io.inc" 14 | 15 | segment .data 16 | prompt1 db "Enter a number: ", 0 ; don't forget nul terminator 17 | prompt2 db "Enter another number: ", 0 18 | outmsg1 db "You entered ", 0 19 | outmsg2 db " and ", 0 20 | outmsg3 db ", the sum of these is ", 0 21 | 22 | segment .bss 23 | ; 24 | ; These labels refer to double words used to store the inputs 25 | ; 26 | input1 resd 1 27 | input2 resd 1 28 | 29 | 30 | 31 | segment .text 32 | global _asm_main 33 | _asm_main: 34 | enter 0,0 ; setup routine 35 | pusha 36 | 37 | mov eax, prompt1 ; print out prompt 38 | call print_string 39 | 40 | mov ebx, input1 ; store address of input1 into ebx 41 | mov ecx, ret1 ; store return address into ecx 42 | jmp short get_int ; read integer 43 | ret1: 44 | mov eax, prompt2 ; print out prompt 45 | call print_string 46 | 47 | mov ebx, input2 48 | mov ecx, $ + 7 ; ecx = this address + 7 49 | jmp short get_int 50 | 51 | mov eax, [input1] ; eax = dword at input1 52 | add eax, [input2] ; eax += dword at input2 53 | mov ebx, eax ; ebx = eax 54 | ; 55 | ; next print out result message as series of steps 56 | ; 57 | 58 | mov eax, outmsg1 59 | call print_string ; print out first message 60 | mov eax, [input1] 61 | call print_int ; print out input1 62 | mov eax, outmsg2 63 | call print_string ; print out second message 64 | mov eax, [input2] 65 | call print_int ; print out input2 66 | mov eax, outmsg3 67 | call print_string ; print out third message 68 | mov eax, ebx 69 | call print_int ; print out sum (ebx) 70 | call print_nl ; print new-line 71 | 72 | popa 73 | mov eax, 0 ; return back to C 74 | leave 75 | ret 76 | ; 77 | ; subprogram get_int 78 | ; Parameters: 79 | ; ebx - address of dword to store integer into 80 | ; ecx - address of instruction to return to 81 | ; Notes: 82 | ; value of eax is destroyed 83 | get_int: 84 | call read_int 85 | mov [ebx], eax ; store input into memory 86 | jmp ecx ; jump back to caller 87 | 88 | 89 | -------------------------------------------------------------------------------- /examples/ms/sub2.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: sub2.asm 5 | ; Subprogram example program 6 | ; 7 | ; To create executable: 8 | ; Using djgpp: 9 | ; nasm -f coff sub2.asm 10 | ; gcc -o sub1 sub2.o driver.c asm_io.o 11 | ; 12 | ; Using Borland C/C++ 13 | ; nasm -f obj sub2.asm 14 | ; bcc32 sub2.obj driver.c asm_io.obj 15 | 16 | %include "asm_io.inc" 17 | 18 | segment .data 19 | prompt1 db "Enter a number: ", 0 ; don't forget nul terminator 20 | prompt2 db "Enter another number: ", 0 21 | outmsg1 db "You entered ", 0 22 | outmsg2 db " and ", 0 23 | outmsg3 db ", the sum of these is ", 0 24 | 25 | segment .bss 26 | ; 27 | ; These labels refer to double words used to store the inputs 28 | ; 29 | input1 resd 1 30 | input2 resd 1 31 | 32 | 33 | 34 | segment .text 35 | global _asm_main 36 | _asm_main: 37 | enter 0,0 ; setup routine 38 | pusha 39 | 40 | mov eax, prompt1 ; print out prompt 41 | call print_string 42 | 43 | mov ebx, input1 ; store address of input1 into ebx 44 | call get_int ; read integer 45 | 46 | mov eax, prompt2 ; print out prompt 47 | call print_string 48 | 49 | mov ebx, input2 50 | call get_int 51 | 52 | mov eax, [input1] ; eax = dword at input1 53 | add eax, [input2] ; eax += dword at input2 54 | mov ebx, eax ; ebx = eax 55 | ; 56 | ; next print out result message as series of steps 57 | ; 58 | 59 | mov eax, outmsg1 60 | call print_string ; print out first message 61 | mov eax, [input1] 62 | call print_int ; print out input1 63 | mov eax, outmsg2 64 | call print_string ; print out second message 65 | mov eax, [input2] 66 | call print_int ; print out input2 67 | mov eax, outmsg3 68 | call print_string ; print out third message 69 | mov eax, ebx 70 | call print_int ; print out sum (ebx) 71 | call print_nl ; print new-line 72 | 73 | popa 74 | mov eax, 0 ; return back to C 75 | leave 76 | ret 77 | ; 78 | ; subprogram get_int 79 | ; Parameters: 80 | ; ebx - address of word to store integer into 81 | ; Notes: 82 | ; value of eax is destroyed 83 | get_int: 84 | call read_int 85 | mov [ebx], eax ; store input into memory 86 | ret ; jump back to caller 87 | 88 | 89 | -------------------------------------------------------------------------------- /examples/ms/sub4.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: sub4.asm 5 | ; Subprogram example 6 | 7 | %include "asm_io.inc" 8 | 9 | ; 10 | ; subprogram get_int 11 | ; Parameters (in order pushed on stack) 12 | ; number of input (at [ebp + 12]) 13 | ; address of word to store input into (at [ebp + 8]) 14 | ; Notes: 15 | ; values of eax and ebx are destroyed 16 | segment .data 17 | prompt db ") Enter an integer number (0 to quit): ", 0 18 | 19 | segment .bss 20 | 21 | 22 | 23 | segment .text 24 | global get_int, print_sum 25 | get_int: 26 | enter 0,0 27 | 28 | mov eax, [ebp + 12] 29 | call print_int 30 | 31 | mov eax, prompt 32 | call print_string 33 | 34 | call read_int 35 | mov ebx, [ebp + 8] 36 | mov [ebx], eax ; store input into memory 37 | 38 | leave 39 | ret ; jump back to caller 40 | 41 | ; subprogram print_sum 42 | ; prints out the sum 43 | ; Parameter: 44 | ; sum to print out (at [ebp+8]) 45 | ; Note: destroys value of eax 46 | ; 47 | segment .data 48 | result db "The sum is ", 0 49 | 50 | segment .text 51 | print_sum: 52 | enter 0,0 53 | 54 | mov eax, result 55 | call print_string 56 | 57 | mov eax, [ebp+8] 58 | call print_int 59 | call print_nl 60 | 61 | leave 62 | ret 63 | 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /examples/ms/sub5.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: sub5.asm 5 | ; Subprogram to C interfacing example 6 | 7 | %include "asm_io.inc" 8 | 9 | ; subroutine _calc_sum 10 | ; finds the sum of the integers 1 through n 11 | ; Parameters: 12 | ; n - what to sum up to (at [ebp + 8]) 13 | ; sump - pointer to int to store sum into (at [ebp + 12]) 14 | ; pseudo C code: 15 | ; void calc_sum( int n, int * sump ) 16 | ; { 17 | ; int i, sum = 0; 18 | ; for( i=1; i <= n; i++ ) 19 | ; sum += i; 20 | ; *sump = sum; 21 | ; } 22 | ; 23 | ; To assemble: 24 | ; DJGPP: nasm -f coff sub5.asm 25 | ; Borland: nasm -f obj sub5.asm 26 | 27 | segment .text 28 | global _calc_sum 29 | ; 30 | ; local variable: 31 | ; sum at [ebp-4] 32 | _calc_sum: 33 | enter 4,0 ; allocate room for sum on stack 34 | push ebx ; IMPORTANT! 35 | 36 | mov dword [ebp-4],0 ; sum = 0 37 | dump_stack 1, 2, 4 ; print out stack from ebp-8 to ebp+16 38 | mov ecx, 1 ; ecx is i in pseudocode 39 | for_loop: 40 | cmp ecx, [ebp+8] ; cmp i and n 41 | jnle end_for ; if not i <= n, quit 42 | 43 | add [ebp-4], ecx ; sum += i 44 | inc ecx 45 | jmp short for_loop 46 | 47 | end_for: 48 | mov ebx, [ebp+12] ; ebx = sump 49 | mov eax, [ebp-4] ; eax = sum 50 | mov [ebx], eax 51 | 52 | pop ebx ; restore ebx 53 | leave 54 | ret 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /examples/ms/sub6.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: sub6.asm 5 | ; Subprogram to C interfacing example 6 | 7 | ; subroutine _calc_sum 8 | ; finds the sum of the integers 1 through n 9 | ; Parameters: 10 | ; n - what to sum up to (at [ebp + 8]) 11 | ; Return value: 12 | ; value of sum 13 | ; pseudo C code: 14 | ; int calc_sum( int n ) 15 | ; { 16 | ; int i, sum = 0; 17 | ; for( i=1; i <= n; i++ ) 18 | ; sum += i; 19 | ; return sum; 20 | ; } 21 | ; 22 | ; To assemble: 23 | ; DJGPP: nasm -f coff sub6.asm 24 | ; Borland: nasm -f obj sub6.asm 25 | 26 | segment .text 27 | global _calc_sum 28 | ; 29 | ; local variable: 30 | ; sum at [ebp-4] 31 | _calc_sum: 32 | enter 4,0 ; make room for sum on stack 33 | 34 | mov dword [ebp-4],0 ; sum = 0 35 | mov ecx, 1 ; ecx is i in pseudocode 36 | for_loop: 37 | cmp ecx, [ebp+8] ; cmp i and n 38 | jnle end_for ; if not i <= n, quit 39 | 40 | add [ebp-4], ecx ; sum += i 41 | inc ecx 42 | jmp short for_loop 43 | 44 | end_for: 45 | mov eax, [ebp-4] ; eax = sum 46 | 47 | leave 48 | ret 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /examples/ms/test_big_int.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * file: big_int_test.cpp 3 | * A small test program for the Big_int class 4 | */ 5 | #include "big_int.hpp" 6 | #include 7 | 8 | // Borland (or at least bcc32 ver 5.2) doesn't support the std namespace 9 | #if ! ( ( defined(__BORLANDC__) && __BORLANDC__ < 0x550 ) || defined(__WATCOMC__) ) 10 | using namespace std; 11 | #endif 12 | 13 | int main() 14 | { 15 | try { 16 | // 12345678901234567890 17 | Big_int b(5,"8000000000000a00b"); 18 | Big_int a(5,"80000000000010230"); 19 | Big_int c = a + b; 20 | cout << a << " + " << b << " = " << c << endl; 21 | for( int i=0; i < 2; i++ ) { 22 | c = c + a; 23 | cout << "c = " << c << endl; 24 | } 25 | cout << "c-1 = " << c - Big_int(5,1) << endl; 26 | Big_int d(5, "12345678"); 27 | cout << "d = " << d << endl; 28 | cout << "c == d " << (c == d) << endl; 29 | cout << "c > d " << (c > d) << endl; 30 | } 31 | catch( const char * str ) { 32 | cerr << "Caught: " << str << endl; 33 | } 34 | catch( Big_int::Overflow ) { 35 | cerr << "Overflow" << endl; 36 | } 37 | catch( Big_int::Size_mismatch ) { 38 | cerr << "Size mismatch" << endl; 39 | } 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /examples/watcom-ex.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/humanshell/assembly/474346d24ed2e2abb0e4edd9dc085e6b84104001/examples/watcom-ex.zip -------------------------------------------------------------------------------- /examples/watcom/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Watcom makefile 3 | # Use with wmake using the -ms switch 4 | # 5 | 6 | .SUFFIXES: 7 | .SUFFIXES: .obj .asm .cpp .c 8 | 9 | AS=nasm 10 | ASFLAGS= -f obj 11 | CFLAGS= -fpi87 12 | CC=wcl386 13 | CXX=wcl386 14 | CXXFLAGS=-xs -fpi87 15 | 16 | .asm.obj: 17 | $(AS) $(ASFLAGS) $*.asm 18 | 19 | .cpp.obj: 20 | $(CXX) -c $(CXXFLAGS) $*.cpp 21 | 22 | .c.obj: 23 | $(CC) -c $(CFLAGS) $*.c 24 | 25 | all: prime.exe math.exe sub1.exe sub2.exe sub3.exe sub4.exe sub5.exe sub6.exe first.exe memex.exe dmaxt.exe asm_io.obj fprime.exe quadt.exe test_big_int.exe 26 | 27 | prime.exe: driver.obj prime.obj asm_io.obj 28 | $(CC) $(CFLAGS) -fe=prime.exe driver.obj prime.obj asm_io.obj 29 | 30 | math.exe : driver.obj math.obj asm_io.obj 31 | $(CC) $(CFLAGS) -fe=math.exe driver.obj math.obj asm_io.obj 32 | 33 | first.exe : driver.obj first.obj asm_io.obj 34 | $(CC) $(CFLAGS) -fe=first.exe driver.obj first.obj asm_io.obj 35 | 36 | sub1.exe : driver.obj sub1.obj asm_io.obj 37 | $(CC) $(CFLAGS) -fe=sub1.exe driver.obj sub1.obj asm_io.obj 38 | 39 | sub2.exe : driver.obj sub2.obj asm_io.obj 40 | $(CC) $(CFLAGS) -fe=sub2.exe driver.obj sub2.obj asm_io.obj 41 | 42 | sub3.exe : driver.obj sub3.obj asm_io.obj 43 | $(CC) $(CFLAGS) -fe=sub3.exe driver.obj sub3.obj asm_io.obj 44 | 45 | sub4.exe : driver.obj sub4.obj main4.obj asm_io.obj 46 | $(CC) $(CFLAGS) -fe=sub4.exe driver.obj sub4.obj main4.obj asm_io.obj 47 | 48 | sub5.exe : main5.obj sub5.obj asm_io.obj 49 | $(CC) $(CFLAGS) -fe=sub5.exe main5.obj sub5.obj asm_io.obj 50 | 51 | sub6.exe : main6.obj sub6.obj 52 | $(CC) $(CFLAGS) -fe=sub6.exe main6.obj sub6.obj 53 | 54 | asm_io.obj : asm_io.asm 55 | $(AS) $(ASFLAGS) -d OBJ_TYPE -d WATCOM asm_io.asm 56 | 57 | array1.exe : driver.obj array1.obj array1c.obj 58 | $(CC) $(CFLAGS) -fe=array1.exe array1.obj array1c.obj asm_io.obj 59 | 60 | memex.exe : memex.obj memory.obj 61 | $(CC) $(CFLAGS) -fe=memex.exe memex.obj memory.obj 62 | 63 | dmaxt.exe : dmaxt.obj dmax.obj 64 | $(CC) $(CFLAGS) -fe=dmaxt.exe dmaxt.obj dmax.obj 65 | 66 | quadt.exe : quadt.obj quad.obj 67 | $(CC) $(CFLAGS) -fe=quadt.exe quadt.obj quad.obj 68 | 69 | readt.exe : readt.obj read.obj 70 | $(CC) $(CFLAGS) -fe=readt.exe readt.obj read.obj 71 | 72 | fprime.exe : fprime.obj prime2.obj 73 | $(CC) $(CFLAGS) -fe=fprime.exe fprime.obj prime2.obj 74 | 75 | test_big_int.exe : test_big_int.obj big_int.obj big_math.obj 76 | $(CXX) $(CXXFLAGS) -fe=test_big_int.exe test_big_int.obj big_int.obj big_math.obj 77 | 78 | big_int.obj : big_int.hpp 79 | 80 | test_big_int.obj : big_int.hpp 81 | 82 | first.obj : asm_io.inc first.asm 83 | 84 | sub1.obj : asm_io.inc 85 | 86 | sub2.obj : asm_io.inc 87 | 88 | sub3.obj : asm_io.inc 89 | 90 | sub4.obj : asm_io.inc 91 | 92 | main4.obj : asm_io.inc 93 | 94 | driver.obj : driver.c 95 | 96 | 97 | clean : 98 | del *.obj -------------------------------------------------------------------------------- /examples/watcom/array1c.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Driver file for array1.asm file 3 | */ 4 | 5 | #include 6 | 7 | #include "cdecl.h" 8 | 9 | int PRE_CDECL asm_main( void ) POST_CDECL; 10 | void PRE_CDECL dump_line( void ) POST_CDECL; 11 | 12 | int main() 13 | { 14 | int ret_status; 15 | ret_status = asm_main(); 16 | return ret_status; 17 | } 18 | 19 | /* 20 | * function dump_line 21 | * dumps all chars left in current line from input buffer 22 | */ 23 | void dump_line() 24 | { 25 | int ch; 26 | 27 | while( (ch = getchar()) != EOF && ch != '\n') 28 | /* null body*/ ; 29 | } 30 | 31 | -------------------------------------------------------------------------------- /examples/watcom/asm_io.inc: -------------------------------------------------------------------------------- 1 | extern read_int, print_int, print_string 2 | extern read_char, print_char, print_nl 3 | extern sub_dump_regs, sub_dump_mem, sub_dump_math, sub_dump_stack 4 | 5 | %macro dump_regs 1 6 | push dword %1 7 | call sub_dump_regs 8 | %endmacro 9 | 10 | 11 | ; 12 | ; usage: dump_mem label, start-address, # paragraphs 13 | %macro dump_mem 3 14 | push dword %1 15 | push dword %2 16 | push dword %3 17 | call sub_dump_mem 18 | %endmacro 19 | 20 | %macro dump_math 1 21 | push dword %1 22 | call sub_dump_math 23 | %endmacro 24 | 25 | %macro dump_stack 3 26 | push dword %3 27 | push dword %2 28 | push dword %1 29 | call sub_dump_stack 30 | %endmacro -------------------------------------------------------------------------------- /examples/watcom/asm_io.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/humanshell/assembly/474346d24ed2e2abb0e4edd9dc085e6b84104001/examples/watcom/asm_io.obj -------------------------------------------------------------------------------- /examples/watcom/bitcount.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* 4 | * function bit_count 5 | * Counts the number of bits on (i.e., = 1) in an unsigned int 6 | * (This code assumes that an int is 32-bits!) 7 | * Parameter: 8 | * x - number to count bits of 9 | * Return value: 10 | * number of bits on in x 11 | */ 12 | int bit_count(unsigned int x ) 13 | { 14 | static unsigned int mask[] = { 0x55555555, 15 | 0x33333333, 16 | 0x0F0F0F0F, 17 | 0x00FF00FF, 18 | 0x0000FFFF }; 19 | int i; 20 | int shift; /* number of positions to shift to right */ 21 | 22 | for( i=0, shift=1; i < 5; i++, shift *= 2 ) 23 | x = (x & mask[i]) + ( (x >> shift) & mask[i] ); 24 | return x; 25 | } 26 | 27 | 28 | int main() 29 | { 30 | unsigned int x; 31 | 32 | printf("Enter a number: "); 33 | scanf("%i", &x); 34 | printf("There are %d bits on in %X\n", bit_count(x), x); 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /examples/watcom/bitcount2.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static unsigned char byte_bit_count[256]; /* lookup table */ 4 | 5 | void initialize_count_bits() 6 | { 7 | int cnt, i, data; 8 | 9 | for( i = 0; i < 256; i++ ) { 10 | cnt = 0; 11 | data = i; 12 | while( data != 0 ) { 13 | data = data & (data - 1); 14 | cnt++; 15 | } 16 | byte_bit_count[i] = cnt; 17 | printf("%d %d\n", i, byte_bit_count[i]); 18 | } 19 | } 20 | 21 | int count_bits( unsigned int data ) 22 | { 23 | const unsigned char * dword = ( unsigned char *) & data; 24 | 25 | return byte_bit_count[dword[0]] + byte_bit_count[dword[1]] + 26 | byte_bit_count[dword[2]] + byte_bit_count[dword[3]]; 27 | } 28 | 29 | int main() 30 | { 31 | unsigned int x; 32 | 33 | initialize_count_bits(); 34 | printf("Enter a number: "); 35 | scanf("%i", &x); 36 | printf("There are %d bits on in %X\n", count_bits(x), x); 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /examples/watcom/cdecl.h: -------------------------------------------------------------------------------- 1 | #ifndef CDECL_HEADER_FILE 2 | #define CDECL_HEADER_FILE 3 | 4 | #if defined(__GNUC__) 5 | # define PRE_CDECL 6 | # define POST_CDECL __attribute__((cdecl)) 7 | #else 8 | # define PRE_CDECL __cdecl 9 | # define POST_CDECL 10 | #endif 11 | 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /examples/watcom/dmax.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: dmax.asm 5 | 6 | global _dmax 7 | 8 | ; Watcom doesnt pass floats back on the coprocessor stack' 9 | ; Instead, the address of the location with the return value 10 | ; is passed back in EAX 11 | segment _BSS public align=4 class=BSS use32 12 | return_value resq 1 ; quadword to store result into 13 | 14 | 15 | segment _TEXT public align=1 class=CODE use32 16 | ; function _dmax 17 | ; returns the larger of its two double arguments 18 | ; C prototype 19 | ; double dmax( double d1, double d2 ) 20 | ; Parameters: 21 | ; d1 - first double 22 | ; d2 - second double 23 | ; Return value: 24 | ; larger of d1 and d2 25 | 26 | ; next, some helpful symbols are defined 27 | 28 | %define d1 [ebp+8] 29 | %define d2 [ebp+16] 30 | 31 | _dmax: 32 | enter 0, 0 33 | 34 | fld qword d2 35 | fld qword d1 ; ST0 = d1, ST1 = d2 36 | fcomip st1 ; ST0 = d2 37 | jna short d2_bigger 38 | fcomp st0 ; pop d2 from stack 39 | fld qword d1 ; ST0 = d1 40 | 41 | d2_bigger: ; if d2 is bigger, nothing to do 42 | mov eax, return_value ; address of quadword with result 43 | fstp qword [eax] ; store result at location 44 | 45 | exit: 46 | leave 47 | ret 48 | 49 | 50 | -------------------------------------------------------------------------------- /examples/watcom/dmaxt.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "cdecl.h" 4 | 5 | double PRE_CDECL dmax( double, double ) POST_CDECL; 6 | 7 | int main() 8 | { 9 | double d1, d2; 10 | 11 | printf("Enter two doubles: "); 12 | scanf("%lf %lf", &d1, &d2); 13 | 14 | printf("The larger of %g and %g is %g\n", d1, d2, dmax(d1,d2)); 15 | return 0; 16 | } 17 | 18 | -------------------------------------------------------------------------------- /examples/watcom/driver.c: -------------------------------------------------------------------------------- 1 | #include "cdecl.h" 2 | 3 | int PRE_CDECL asm_main( void ) POST_CDECL; 4 | 5 | int main() 6 | { 7 | int ret_status; 8 | ret_status = asm_main(); 9 | return ret_status; 10 | } 11 | -------------------------------------------------------------------------------- /examples/watcom/fprime.c: -------------------------------------------------------------------------------- 1 | /* 2 | * file: fprime.c 3 | * This program calculates prime numbers 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | #include "cdecl.h" 10 | 11 | /* 12 | * function find_primes 13 | * finds the indicated number of primes 14 | * Parameters: 15 | * a - array to hold primes 16 | * n - how many primes to find 17 | */ 18 | extern void PRE_CDECL find_primes( int * a, unsigned n ) POST_CDECL; 19 | 20 | int main() 21 | { 22 | int status; 23 | unsigned i; 24 | unsigned max; 25 | int * a; 26 | 27 | printf("How many primes do you wish to find? "); 28 | scanf("%u", &max); 29 | 30 | a = calloc( sizeof(int), max); 31 | 32 | if ( a ) { 33 | 34 | find_primes(a,max); 35 | 36 | /* 37 | * print out the last 20 primes found 38 | */ 39 | for(i= ( max > 20 ) ? max - 20 : 0; i < max; i++ ) 40 | printf("%3d %d\n", i+1, a[i]); 41 | 42 | free(a); 43 | status = 0; 44 | } 45 | else { 46 | fprintf(stderr, "Can not create array of %u ints\n", max); 47 | status = 1; 48 | } 49 | 50 | return status; 51 | } 52 | -------------------------------------------------------------------------------- /examples/watcom/main4.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: main4.asm 5 | ; Multi-module subprogram example program 6 | ; 7 | ; To create executable: 8 | ; Using djgpp: 9 | ; nasm -f coff sub4.asm 10 | ; nasm -f coff main4.asm 11 | ; gcc -o sub4 sub4.o main4.o driver.c asm_io.o 12 | ; 13 | ; Using Borland C/C++ 14 | ; nasm -f obj sub4.asm 15 | ; nasm -f obj main4.asm 16 | ; bcc32 sub4.obj main4.asm driver.c asm_io.obj 17 | 18 | %include "asm_io.inc" 19 | 20 | segment _DATA public align=4 class=DATA use32 21 | sum dd 0 22 | 23 | segment _BSS public align=4 class=BSS use32 24 | input resd 1 25 | 26 | group DGROUP _BSS _DATA 27 | 28 | ; 29 | ; psuedo-code algorithm 30 | ; i = 1; 31 | ; sum = 0; 32 | ; while( get_int(i, &input), input != 0 ) { 33 | ; sum += input; 34 | ; i++; 35 | ; } 36 | ; print_sum(num); 37 | 38 | segment _TEXT public align=1 class=CODE use32 39 | global _asm_main 40 | extern get_int, print_sum 41 | _asm_main: 42 | enter 0,0 ; setup routine 43 | pusha 44 | 45 | mov edx, 1 ; edx is 'i' in pseudo-code 46 | while_loop: 47 | push edx ; save i on stack 48 | push dword input ; push address on input on stack 49 | call get_int 50 | add esp, 8 ; remove i and &input from stack 51 | 52 | mov eax, [input] 53 | cmp eax, 0 54 | je end_while 55 | 56 | add [sum], eax ; sum += input 57 | 58 | inc edx 59 | jmp short while_loop 60 | 61 | end_while: 62 | push dword [sum] ; push value of sum onto stack 63 | call print_sum 64 | pop ecx ; remove [sum] from stack 65 | 66 | popa 67 | leave 68 | ret 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /examples/watcom/main5.c: -------------------------------------------------------------------------------- 1 | /* 2 | * file: main5.c 3 | * main C program that uses assembly routine in sub5.asm 4 | * to create executable: 5 | * DJGPP: gcc -o sub5 main5.c sub5.o asm_io.o 6 | * Borland: bcc32 sub5.obj main5.c asm_io.obj 7 | */ 8 | 9 | #include 10 | 11 | #include "cdecl.h" 12 | 13 | void PRE_CDECL calc_sum( int, int * ) POST_CDECL; /* prototype for assembly routine */ 14 | 15 | int main( void ) 16 | { 17 | int n, sum; 18 | 19 | printf("Sum integers up to: "); 20 | scanf("%d", &n); 21 | calc_sum(n, &sum); 22 | printf("Sum is %d\n", sum); 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /examples/watcom/main6.c: -------------------------------------------------------------------------------- 1 | /* 2 | * file: main6.c 3 | * main C program that uses assembly routine in sub5.asm 4 | * to create executable: 5 | * DJGPP: gcc -o sub5 main5.c sub5.o 6 | * Borland: bcc32 sub5.obj main5.c 7 | */ 8 | 9 | #include 10 | 11 | #include "cdecl.h" 12 | 13 | int PRE_CDECL calc_sum( int ) POST_CDECL; /* prototype for assembly routine */ 14 | 15 | int main( void ) 16 | { 17 | int n, sum; 18 | 19 | printf("Sum integers up to: "); 20 | scanf("%d", &n); 21 | sum = calc_sum(n); 22 | printf("Sum is %d\n", sum); 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /examples/watcom/math.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: math.asm 5 | ; This program demonstrates how the integer multiplication and division 6 | ; instructions work. 7 | ; 8 | ; To create executable: 9 | ; nasm -f coff math.asm 10 | ; gcc -o math math.o driver.c asm_io.o 11 | 12 | %include "asm_io.inc" 13 | 14 | segment _DATA public align=4 class=DATA use32 15 | ; 16 | ; Output strings 17 | ; 18 | prompt db "Enter a number: ", 0 19 | square_msg db "Square of input is ", 0 20 | cube_msg db "Cube of input is ", 0 21 | cube25_msg db "Cube of input times 25 is ", 0 22 | quot_msg db "Quotient of cube/100 is ", 0 23 | rem_msg db "Remainder of cube/100 is ", 0 24 | neg_msg db "The negation of the remainder is ", 0 25 | 26 | segment _BSS public align=4 class=BSS use32 27 | input resd 1 28 | 29 | 30 | segment _TEXT public align=1 class=CODE use32 31 | global _asm_main 32 | _asm_main: 33 | enter 0,0 ; setup routine 34 | pusha 35 | 36 | mov eax, prompt 37 | call print_string 38 | 39 | call read_int 40 | mov [input], eax 41 | 42 | imul eax ; edx:eax = eax * eax 43 | mov ebx, eax ; save answer in ebx 44 | mov eax, square_msg 45 | call print_string 46 | mov eax, ebx 47 | call print_int 48 | call print_nl 49 | 50 | mov ebx, eax 51 | imul ebx, [input] ; ebx *= [input] 52 | mov eax, cube_msg 53 | call print_string 54 | mov eax, ebx 55 | call print_int 56 | call print_nl 57 | 58 | imul ecx, ebx, 25 ; ecx = ebx*25 59 | mov eax, cube25_msg 60 | call print_string 61 | mov eax, ecx 62 | call print_int 63 | call print_nl 64 | 65 | mov eax, ebx 66 | cdq ; initialize edx by sign extension 67 | mov ecx, 100 ; can't divide by immediate value 68 | idiv ecx ; edx:eax / ecx 69 | mov ecx, eax ; save quotient into ecx 70 | mov eax, quot_msg 71 | call print_string 72 | mov eax, ecx 73 | call print_int 74 | call print_nl 75 | mov eax, rem_msg 76 | call print_string 77 | mov eax, edx 78 | call print_int 79 | call print_nl 80 | 81 | neg edx ; negate the remainder 82 | mov eax, neg_msg 83 | call print_string 84 | mov eax, edx 85 | call print_int 86 | call print_nl 87 | 88 | popa 89 | mov eax, 0 ; return back to C 90 | leave 91 | ret 92 | 93 | 94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /examples/watcom/max.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: max.asm 5 | ; This example demostrates how to avoid conditional branches 6 | 7 | %include "asm_io.inc" 8 | segment _DATA public align=4 class=DATA use32 9 | 10 | message1 db "Enter a number: ",0 11 | message2 db "Enter another number: ", 0 12 | message3 db "The larger number is: ", 0 13 | 14 | segment _BSS public align=4 class=BSS use32 15 | 16 | input1 resd 1 ; first number entered 17 | 18 | group DGROUP _BSS _DATA 19 | 20 | segment _TEXT public align=1 class=CODE use32 21 | global _asm_main 22 | _asm_main: 23 | enter 0,0 ; setup routine 24 | pusha 25 | 26 | mov eax, message1 ; print out first message 27 | call print_string 28 | call read_int ; input first number 29 | mov [input1], eax 30 | 31 | mov eax, message2 ; print out second message 32 | call print_string 33 | call read_int ; input second number (in eax) 34 | 35 | xor ebx, ebx ; ebx = 0 36 | cmp eax, [input1] ; compare second and first number 37 | setg bl ; ebx = (input2 > input1) ? 1 : 0 38 | neg ebx ; ebx = (input2 > input1) ? 0xFFFFFFFF : 0 39 | mov ecx, ebx ; ecx = (input2 > input1) ? 0xFFFFFFFF : 0 40 | and ecx, eax ; ecx = (input2 > input1) ? input2 : 0 41 | not ebx ; ebx = (input2 > input1) ? 0 : 0xFFFFFFFF 42 | and ebx, [input1] ; ebx = (input2 > input1) ? 0 : input1 43 | or ecx, ebx ; ecx = (input2 > input1) ? input2 : input1 44 | 45 | mov eax, message3 ; print out result 46 | call print_string 47 | mov eax, ecx 48 | call print_int 49 | call print_nl 50 | 51 | popa 52 | mov eax, 0 ; return back to C 53 | leave 54 | ret 55 | 56 | 57 | -------------------------------------------------------------------------------- /examples/watcom/memex.c: -------------------------------------------------------------------------------- 1 | /* 2 | * file: memex.c 3 | */ 4 | 5 | #include 6 | 7 | #include "cdecl.h" 8 | 9 | #define STR_SIZE 30 10 | /* 11 | * prototypes 12 | */ 13 | 14 | void PRE_CDECL asm_copy( void *, 15 | const void *, 16 | unsigned ) POST_CDECL; 17 | 18 | void * PRE_CDECL asm_find( const void *, 19 | char target, 20 | unsigned ) POST_CDECL; 21 | 22 | unsigned PRE_CDECL asm_strlen( const char * ) POST_CDECL; 23 | 24 | void PRE_CDECL asm_strcpy( char *, 25 | const char * ) POST_CDECL; 26 | 27 | int main() 28 | { 29 | char st1[STR_SIZE] = "test string"; 30 | char st2[STR_SIZE]; 31 | char * st; 32 | char ch; 33 | 34 | asm_copy(st2, st1, STR_SIZE); /* copy all 30 chars of string */ 35 | printf("%s\n", st2); 36 | 37 | printf("Enter a char: "); /* look for byte in string */ 38 | scanf("%c%*[^\n]", &ch); 39 | st = asm_find(st2, ch, STR_SIZE); 40 | if ( st ) 41 | printf("Found it: %s\n", st); 42 | else 43 | printf("Not found\n"); 44 | 45 | st1[0] = 0; 46 | printf("Enter string:"); 47 | scanf("%s", st1); 48 | printf("len = %u\n", asm_strlen(st1)); 49 | 50 | asm_strcpy( st2, st1); /* copy meaningful data in string */ 51 | printf("%s\n", st2 ); 52 | 53 | return 0; 54 | } 55 | 56 | -------------------------------------------------------------------------------- /examples/watcom/quadt.c: -------------------------------------------------------------------------------- 1 | /* 2 | * file: quadt.c 3 | * Test file for quad.asm 4 | */ 5 | 6 | #include 7 | 8 | #include "cdecl.h" 9 | 10 | int PRE_CDECL quadratic( double, double, double, double *, double *) POST_CDECL; 11 | 12 | int main() 13 | { 14 | double a,b,c, root1, root2; 15 | 16 | printf("Enter a, b, c: "); 17 | scanf("%lf %lf %lf", &a, &b, &c); 18 | if (quadratic( a, b, c, &root1, &root2) ) 19 | printf("roots: %.10g %.10g\n", root1, root2); 20 | else 21 | printf("No real roots\n"); 22 | return 0; 23 | } 24 | 25 | -------------------------------------------------------------------------------- /examples/watcom/read.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: read.asm 5 | ; This subroutine reads an array of doubles from a file 6 | 7 | segment _DATA public align=4 class=DATA use32 8 | format db "%lf", 0 ; format for fscanf() 9 | 10 | segment _BSS public align=4 class=BSS use32 11 | 12 | group DGROUP _BSS _DATA 13 | 14 | segment _TEXT public align=1 class=CODE use32 15 | global _read_doubles 16 | extern fscanf_ 17 | 18 | %define SIZEOF_DOUBLE 8 19 | %define FP dword [ebp + 8] 20 | %define ARRAYP dword [ebp + 12] 21 | %define ARRAY_SIZE dword [ebp + 16] 22 | %define TEMP_DOUBLE [ebp - 8] 23 | 24 | ; 25 | ; function _read_doubles 26 | ; C prototype: 27 | ; int read_doubles( FILE * fp, double * arrayp, int array_size ); 28 | ; This function reads doubles from a text file into an array, until 29 | ; EOF or array is full. 30 | ; Parameters: 31 | ; fp - FILE pointer to read from (must be open for input) 32 | ; arrayp - pointer to double array to read into 33 | ; array_size - number of elements in array 34 | ; Return value: 35 | ; number of doubles stored into array (in EAX) 36 | 37 | _read_doubles: 38 | push ebp 39 | mov ebp,esp 40 | sub esp, SIZEOF_DOUBLE ; define one double on stack 41 | 42 | push esi ; save esi 43 | mov esi, ARRAYP ; esi = ARRAYP 44 | xor edx, edx ; edx = array index (initially 0) 45 | 46 | while_loop: 47 | cmp edx, ARRAY_SIZE ; is edx < ARRAY_SIZE? 48 | jnl short quit ; if not, quit loop 49 | ; 50 | ; call fscanf() to read a double into TEMP_DOUBLE 51 | ; fscanf() might change edx so save it 52 | ; 53 | push edx ; save edx 54 | lea eax, TEMP_DOUBLE 55 | push eax ; push &TEMP_DOUBLE 56 | push dword format ; push &format 57 | push FP ; push file pointer 58 | call fscanf_ 59 | add esp, 12 60 | pop edx ; restore edx 61 | cmp eax, 1 ; did fscanf return 1? 62 | jne short quit ; if not, quit loop 63 | 64 | ; 65 | ; copy TEMP_DOUBLE into ARRAYP[edx] 66 | ; (The 8-bytes of the double are copied by two 4-byte copies) 67 | ; 68 | mov eax, [ebp - 8] 69 | mov [esi + 8*edx], eax ; first copy lowest 4 bytes 70 | mov eax, [ebp - 4] 71 | mov [esi + 8*edx + 4], eax ; next copy highest 4 bytes 72 | 73 | inc edx 74 | jmp while_loop 75 | 76 | quit: 77 | pop esi ; restore esi 78 | 79 | mov eax, edx ; store return value into eax 80 | 81 | mov esp, ebp 82 | pop ebp 83 | ret 84 | 85 | -------------------------------------------------------------------------------- /examples/watcom/readt.c: -------------------------------------------------------------------------------- 1 | /* 2 | * file: readt.c 3 | * This program tests the 32-bit read_doubles() assembly procedure. 4 | * It reads the doubles from stdin. 5 | * (Use redirection to read from file.) 6 | */ 7 | 8 | #include 9 | 10 | #include "cdecl.h" 11 | 12 | extern int PRE_CDECL read_doubles( FILE *, double *, int ) POST_CDECL; 13 | 14 | #define MAX 100 15 | 16 | int main() 17 | { 18 | int i,n; 19 | double a[MAX]; 20 | 21 | n = read_doubles(stdin, a, MAX); 22 | 23 | for( i=0; i < n; i++ ) 24 | printf("%3d %g\n", i, a[i]); 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /examples/watcom/skel.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: skel.asm 5 | ; This file is a skeleton that can be used to start assembly programs. 6 | 7 | %include "asm_io.inc" 8 | segment _DATA public align=4 class=DATA use32 9 | ; 10 | ; initialized data is put in the data segment here 11 | ; 12 | 13 | 14 | segment _BSS public align=4 class=BSS use32 15 | ; 16 | ; uninitialized data is put in the bss segment 17 | ; 18 | 19 | 20 | group DGROUP _BSS _DATA 21 | 22 | segment _TEXT public align=1 class=CODE use32 23 | global _asm_main 24 | _asm_main: 25 | enter 0,0 ; setup routine 26 | pusha 27 | 28 | ; 29 | ; code is put in the text segment. Do not modify the code before 30 | ; or after this comment. 31 | ; 32 | 33 | popa 34 | mov eax, 0 ; return back to C 35 | leave 36 | ret 37 | 38 | 39 | -------------------------------------------------------------------------------- /examples/watcom/sub1.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: sub1.asm 5 | ; Subprogram example program 6 | ; 7 | ; To create executable: 8 | ; Using djgpp: 9 | ; nasm -f coff sub1.asm 10 | ; gcc -o sub1 sub1.o driver.c asm_io.o 11 | ; 12 | 13 | %include "asm_io.inc" 14 | 15 | segment _DATA public align=4 class=DATA use32 16 | prompt1 db "Enter a number: ", 0 ; don't forget nul terminator 17 | prompt2 db "Enter another number: ", 0 18 | outmsg1 db "You entered ", 0 19 | outmsg2 db " and ", 0 20 | outmsg3 db ", the sum of these is ", 0 21 | 22 | segment _BSS public align=4 class=BSS use32 23 | ; 24 | ; These labels refer to double words used to store the inputs 25 | ; 26 | input1 resd 1 27 | input2 resd 1 28 | 29 | group DGROUP _BSS _DATA 30 | 31 | segment _TEXT public align=1 class=CODE use32 32 | global _asm_main 33 | _asm_main: 34 | enter 0,0 ; setup routine 35 | pusha 36 | 37 | mov eax, prompt1 ; print out prompt 38 | call print_string 39 | 40 | mov ebx, input1 ; store address of input1 into ebx 41 | mov ecx, ret1 ; store return address into ecx 42 | jmp short get_int ; read integer 43 | ret1: 44 | mov eax, prompt2 ; print out prompt 45 | call print_string 46 | 47 | mov ebx, input2 48 | mov ecx, $ + 7 ; ecx = this address + 7 49 | jmp short get_int 50 | 51 | mov eax, [input1] ; eax = dword at input1 52 | add eax, [input2] ; eax += dword at input2 53 | mov ebx, eax ; ebx = eax 54 | ; 55 | ; next print out result message as series of steps 56 | ; 57 | 58 | mov eax, outmsg1 59 | call print_string ; print out first message 60 | mov eax, [input1] 61 | call print_int ; print out input1 62 | mov eax, outmsg2 63 | call print_string ; print out second message 64 | mov eax, [input2] 65 | call print_int ; print out input2 66 | mov eax, outmsg3 67 | call print_string ; print out third message 68 | mov eax, ebx 69 | call print_int ; print out sum (ebx) 70 | call print_nl ; print new-line 71 | 72 | popa 73 | mov eax, 0 ; return back to C 74 | leave 75 | ret 76 | ; 77 | ; subprogram get_int 78 | ; Parameters: 79 | ; ebx - address of dword to store integer into 80 | ; ecx - address of instruction to return to 81 | ; Notes: 82 | ; value of eax is destroyed 83 | get_int: 84 | call read_int 85 | mov [ebx], eax ; store input into memory 86 | jmp ecx ; jump back to caller 87 | 88 | 89 | -------------------------------------------------------------------------------- /examples/watcom/sub2.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: sub2.asm 5 | ; Subprogram example program 6 | ; 7 | ; To create executable: 8 | ; Using djgpp: 9 | ; nasm -f coff sub2.asm 10 | ; gcc -o sub1 sub2.o driver.c asm_io.o 11 | ; 12 | ; Using Borland C/C++ 13 | ; nasm -f obj sub2.asm 14 | ; bcc32 sub2.obj driver.c asm_io.obj 15 | 16 | %include "asm_io.inc" 17 | 18 | segment _DATA public align=4 class=DATA use32 19 | prompt1 db "Enter a number: ", 0 ; don't forget nul terminator 20 | prompt2 db "Enter another number: ", 0 21 | outmsg1 db "You entered ", 0 22 | outmsg2 db " and ", 0 23 | outmsg3 db ", the sum of these is ", 0 24 | 25 | segment _BSS public align=4 class=BSS use32 26 | ; 27 | ; These labels refer to double words used to store the inputs 28 | ; 29 | input1 resd 1 30 | input2 resd 1 31 | 32 | group DGROUP _BSS _DATA 33 | 34 | segment _TEXT public align=1 class=CODE use32 35 | global _asm_main 36 | _asm_main: 37 | enter 0,0 ; setup routine 38 | pusha 39 | 40 | mov eax, prompt1 ; print out prompt 41 | call print_string 42 | 43 | mov ebx, input1 ; store address of input1 into ebx 44 | call get_int ; read integer 45 | 46 | mov eax, prompt2 ; print out prompt 47 | call print_string 48 | 49 | mov ebx, input2 50 | call get_int 51 | 52 | mov eax, [input1] ; eax = dword at input1 53 | add eax, [input2] ; eax += dword at input2 54 | mov ebx, eax ; ebx = eax 55 | ; 56 | ; next print out result message as series of steps 57 | ; 58 | 59 | mov eax, outmsg1 60 | call print_string ; print out first message 61 | mov eax, [input1] 62 | call print_int ; print out input1 63 | mov eax, outmsg2 64 | call print_string ; print out second message 65 | mov eax, [input2] 66 | call print_int ; print out input2 67 | mov eax, outmsg3 68 | call print_string ; print out third message 69 | mov eax, ebx 70 | call print_int ; print out sum (ebx) 71 | call print_nl ; print new-line 72 | 73 | popa 74 | mov eax, 0 ; return back to C 75 | leave 76 | ret 77 | ; 78 | ; subprogram get_int 79 | ; Parameters: 80 | ; ebx - address of word to store integer into 81 | ; Notes: 82 | ; value of eax is destroyed 83 | get_int: 84 | call read_int 85 | mov [ebx], eax ; store input into memory 86 | ret ; jump back to caller 87 | 88 | 89 | -------------------------------------------------------------------------------- /examples/watcom/sub4.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: sub4.asm 5 | ; Subprogram example 6 | 7 | %include "asm_io.inc" 8 | 9 | ; 10 | ; subprogram get_int 11 | ; Parameters (in order pushed on stack) 12 | ; number of input (at [ebp + 12]) 13 | ; address of word to store input into (at [ebp + 8]) 14 | ; Notes: 15 | ; values of eax and ebx are destroyed 16 | segment _DATA public align=4 class=DATA use32 17 | prompt db ") Enter an integer number (0 to quit): ", 0 18 | 19 | segment _BSS public align=4 class=BSS use32 20 | 21 | group DGROUP _BSS _DATA 22 | 23 | segment _TEXT public align=1 class=CODE use32 24 | global get_int, print_sum 25 | get_int: 26 | enter 0,0 27 | 28 | mov eax, [ebp + 12] 29 | call print_int 30 | 31 | mov eax, prompt 32 | call print_string 33 | 34 | call read_int 35 | mov ebx, [ebp + 8] 36 | mov [ebx], eax ; store input into memory 37 | 38 | leave 39 | ret ; jump back to caller 40 | 41 | ; subprogram print_sum 42 | ; prints out the sum 43 | ; Parameter: 44 | ; sum to print out (at [ebp+8]) 45 | ; Note: destroys value of eax 46 | ; 47 | segment _DATA 48 | result db "The sum is ", 0 49 | 50 | segment _TEXT 51 | print_sum: 52 | enter 0,0 53 | 54 | mov eax, result 55 | call print_string 56 | 57 | mov eax, [ebp+8] 58 | call print_int 59 | call print_nl 60 | 61 | leave 62 | ret 63 | 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /examples/watcom/sub5.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: sub5.asm 5 | ; Subprogram to C interfacing example 6 | 7 | %include "asm_io.inc" 8 | 9 | ; subroutine _calc_sum 10 | ; finds the sum of the integers 1 through n 11 | ; Parameters: 12 | ; n - what to sum up to (at [ebp + 8]) 13 | ; sump - pointer to int to store sum into (at [ebp + 12]) 14 | ; pseudo C code: 15 | ; void calc_sum( int n, int * sump ) 16 | ; { 17 | ; int i, sum = 0; 18 | ; for( i=1; i <= n; i++ ) 19 | ; sum += i; 20 | ; *sump = sum; 21 | ; } 22 | ; 23 | ; To assemble: 24 | ; DJGPP: nasm -f coff sub5.asm 25 | ; Borland: nasm -f obj sub5.asm 26 | 27 | segment _TEXT public align=1 class=CODE use32 28 | global _calc_sum 29 | ; 30 | ; local variable: 31 | ; sum at [ebp-4] 32 | _calc_sum: 33 | enter 4,0 ; allocate room for sum on stack 34 | push ebx ; IMPORTANT! 35 | 36 | mov dword [ebp-4],0 ; sum = 0 37 | dump_stack 1, 2, 4 ; print out stack from ebp-8 to ebp+16 38 | mov ecx, 1 ; ecx is i in pseudocode 39 | for_loop: 40 | cmp ecx, [ebp+8] ; cmp i and n 41 | jnle end_for ; if not i <= n, quit 42 | 43 | add [ebp-4], ecx ; sum += i 44 | inc ecx 45 | jmp short for_loop 46 | 47 | end_for: 48 | mov ebx, [ebp+12] ; ebx = sump 49 | mov eax, [ebp-4] ; eax = sum 50 | mov [ebx], eax 51 | 52 | pop ebx ; restore ebx 53 | leave 54 | ret 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /examples/watcom/sub6.asm: -------------------------------------------------------------------------------- 1 | 2 | 3 | ; 4 | ; file: sub6.asm 5 | ; Subprogram to C interfacing example 6 | 7 | ; subroutine _calc_sum 8 | ; finds the sum of the integers 1 through n 9 | ; Parameters: 10 | ; n - what to sum up to (at [ebp + 8]) 11 | ; Return value: 12 | ; value of sum 13 | ; pseudo C code: 14 | ; int calc_sum( int n ) 15 | ; { 16 | ; int i, sum = 0; 17 | ; for( i=1; i <= n; i++ ) 18 | ; sum += i; 19 | ; return sum; 20 | ; } 21 | ; 22 | ; To assemble: 23 | ; DJGPP: nasm -f coff sub6.asm 24 | ; Borland: nasm -f obj sub6.asm 25 | 26 | segment _TEXT public align=1 class=CODE use32 27 | global _calc_sum 28 | ; 29 | ; local variable: 30 | ; sum at [ebp-4] 31 | _calc_sum: 32 | enter 4,0 ; make room for sum on stack 33 | 34 | mov dword [ebp-4],0 ; sum = 0 35 | mov ecx, 1 ; ecx is i in pseudocode 36 | for_loop: 37 | cmp ecx, [ebp+8] ; cmp i and n 38 | jnle end_for ; if not i <= n, quit 39 | 40 | add [ebp-4], ecx ; sum += i 41 | inc ecx 42 | jmp short for_loop 43 | 44 | end_for: 45 | mov eax, [ebp-4] ; eax = sum 46 | 47 | leave 48 | ret 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /examples/watcom/test_big_int.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * file: big_int_test.cpp 3 | * A small test program for the Big_int class 4 | */ 5 | #include "big_int.hpp" 6 | #include 7 | 8 | // Borland (or at least bcc32 ver 5.2) doesn't support the std namespace 9 | #if ! ( defined(__BORLANDC__) || defined(__WATCOMC__) ) 10 | using namespace std; 11 | #endif 12 | 13 | int main() 14 | { 15 | try { 16 | // 12345678901234567890 17 | Big_int b(5,"8000000000000a00b"); 18 | Big_int a(5,"80000000000010230"); 19 | Big_int c = a + b; 20 | cout << a << " + " << b << " = " << c << endl; 21 | for( int i=0; i < 2; i++ ) { 22 | c = c + a; 23 | cout << "c = " << c << endl; 24 | } 25 | cout << "c-1 = " << c - Big_int(5,1) << endl; 26 | Big_int d(5, "12345678"); 27 | cout << "d = " << d << endl; 28 | cout << "c == d " << (c == d) << endl; 29 | cout << "c > d " << (c > d) << endl; 30 | } 31 | catch( const char * str ) { 32 | cerr << "Caught: " << str << endl; 33 | } 34 | catch( Big_int::Overflow ) { 35 | cerr << "Overflow" << endl; 36 | } 37 | catch( Big_int::Size_mismatch ) { 38 | cerr << "Size mismatch" << endl; 39 | } 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /newproject.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # newproject.sh - utility script to automate generation of new projects 3 | 4 | NAME=$1 5 | NAME=${NAME:="newproject"} 6 | mkdir $NAME 7 | cp examples/linux/asm_io.inc $NAME/ 8 | cp examples/linux/driver.c $NAME/ 9 | cp examples/linux/cdecl.h $NAME/ 10 | cp examples/linux/asm_io.o $NAME/ 11 | cat examples/linux/skel.asm | sed "s/skel/$NAME/g" > $NAME/${NAME}.asm 12 | echo "# $NAME" > $NAME/README.md 13 | 14 | --------------------------------------------------------------------------------