x86 Assembler (MASM)
COLLATZ PROBLEM
If n is even then divide by 2. If n is odd multiply by 3 and add 1.
A chain is defined as the number of iterations of this method for the calculation to end at 1.
I wrote the following code to solve a problem for a maths challenge.
; longest chain starting with number under 1,000,000
xor edi, edi
align 4
start: mov ecx, 1000000 ; set main loop counter
jmp outer ; loop entry
inner: bt eax, 0 ; test even number
jnc @f ; if no carry number is even
lea eax, [eax*2+eax+1] ; number is odd perform 3n+1
@@: shr eax, 1 ; numbers are all even now so div by 2
inc esi ; increment present number chain
cmp eax, 1 ; if number is 1 we are done with it
jnz inner ; continue chain
cmp esi, edi ; if chain > longest_chain
jb outer ; no, goto outer
mov edi, esi ; yes, update longest_chain
mov ebx, ecx ; save number having longest chain
outer: xor esi, esi ; reset inner loop counter
dec ecx ; decrement outer loop counter
mov eax, ecx ; save as next number to iterate
cmp ecx, 500000 ; assume longest chain > 500000
jnz inner ; if outer loop counter > 0 continue
print str$(ebx) ; print result
exit
|
SPIRAL DIAGONALS
Consider a 1001x1001 numerical spiral such as the 9x9 example below.
73 74 75 76 77 78 79 80 81
72 43 44 45 46 47 48 49 50
71 42 21 22 23 24 25 26 51
70 41 20 7 8 9 10 27 52
69 40 19 6 1 2 11 28 53
68 39 18 5 4 3 12 29 54
67 38 17 16 15 14 13 30 55
66 37 36 35 34 33 32 31 56
65 64 63 62 61 60 59 58 57
Calculate sum of the diagonals in the 1001x1001 spiral.
start: mov ecx, 1 ; first diagonal spiral number
xor ebx, ebx ; determines distance to next diagonal
mov eax, ecx ; begin accumulating sum
inner: add ebx, 2 ; update distance between diagonals
mov edx, 4 ; will use distance for 4 iterations
outer: add ecx, ebx ; go to next diagonal
cmp ecx, 1002001 ; last one?
ja gotit ; yes, go away
add eax, ecx ; no, add to sum
dec edx ; decrement inner loop counter
jz inner ; if zero, reset counter
jmp outer ; next number
gotit: print str$(eax) ; print result
exit
|
KEY GENERATOR
During a recent hacking challenge, the task of reversing an application and providing a key generator to register the application provided an opportunity to write my first key generator. The application was designed for the challenge and I do not condone reversing or "keygenning" applications that are not developed for this purpose.
start:
mov str1, input("Enter username : ") ; I used a 3 character username
mov eax, str1 ; IIRC the algorithm actually required less work for > 3 characters
mov ebx, [eax]
mov ecx, 2 ; #loop iterations
l1: xor eax, eax ; 1st iteration ; 2nd iteration
ror ebx, 8 ; ebx=41004342 ; ebx=42410043 last char
mov al, bl ; ax=0042 mid char ; ax=0043
rol ax, 4 ; ax=0420 ; ax=0430
add al, ah ; bits swapped
push ecx ; preserve count
print right$(hex$(eax),2) ; #1 & #2
pop ecx
dec ecx
jnz l1
mov ecx, 2 ; #loop iterations
l2: xor eax, eax ; 1st iteration ; 2nd iteration
ror ebx, 8 ; ebx=41004342 ; ebx=42410043 last char
mov al, bl ; ax=0042 mid char ; ax=0043
cmp al, 61h ; determine case
jb @f
; lower case, change to upper-20h -eliminates extra jmp
sub al, 40h
@@: add al, 25h ; if upper then al=67
rol ax, 4 ; ax=0670
add al, ah ; ax=0076 bits swapped
push ecx ; preserve count
print right$(hex$(eax),2) ; #3 & #4
pop ecx
ror ebx, 16 ; ebx=43420041 ; 41434200
dec ecx
jnz l2
rol ebx, 16 ; correct ebx, ebx=42004143
xor eax, eax
mov al, bl ; ax=0043
cmp al, 61h ; determine case
jb @f
sub al, 40h ; lower case, change to upper-20h
@@: add al, 23h ; if upper then al=66
rol ax, 4 ; ax=0660
add al, ah ; ax=0066 bits swapped
print right$(hex$(eax),2) ; #5
xor eax, eax
rol ebx, 8 ; ebx=41004342
mov al, bl ; ax=0042 mid char
rol ax, 4 ; ax=0420
add al, ah ; ax=0024 bits swapped
print right$(hex$(eax),2) ; #6
xor eax, eax
ror ebx, 8 ; ebx=42410043
mov al, bl ; ax=0043
rol ax, 4 ; ax=0430
add al, ah ; ax=0034
ror al, 4 ; ax=4003
print right$(hex$(eax),1) ; #7
print SADD("789ABCDEF11112131415161722353781") ; #8
ror ebx, 16 ; manipulate ebx to spew 9th string section
print right$(hex$(ebx),2) ; #9
ror ebx, 12 ; bl=10th string section
print right$(hex$(ebx),1) ; #10
exit
|
SIMPLE DLL
A simple example of a Dynamic Link Library.
This is the first of three files. Save this as mydll.asm.
.386
.model flat, stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
.data
AppName db "my DLL", 0
dllMsg db "This function was called from the DLL.", 0
.code
DllEntry proc hInstance:HINSTANCE, reason:DWORD, reserved1:DWORD
mov eax, TRUE
ret
DllEntry Endp
functionOne proc
invoke MessageBox, NULL, addr dllMsg, addr AppName, MB_OK
ret
functionOne endp
PassParam proc para1:DWORD
invoke MessageBox, NULL, para1, addr AppName, MB_OK
ret
PassParam endp
End DllEntry
Next we need to create our def file. All exported functions should be listed. Save this one as mydll.def.
LIBRARY mydll
EXPORTS functionOne
PassParam
Now we create the driver for testing the dll. Save as usedll.asm.
.386
.model flat, stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
includelib mydll.lib
includelib \masm32\lib\kernel32.lib
functionOne PROTO
PassParam PROTO :DWORD
.data
strParam db "1 Param passed", 0
.code
start:
invoke functionOne
invoke PassParam, addr strParam
invoke ExitProcess, NULL
end start
Finally we can compile mydll.dll and the usedll.exe program.
; DLL
ml /c /coff /Cp mydll.asm
link /DLL /SUBSYSTEM:WINDOWS /DEF:mydll.def /LIBPATH:c:\masm32\lib mydll.obj
; usedll
ml /c /coff /Cp usedll.asm
link /SUBSYSTEM:WINDOWS usedll.obj
|
|