• Welcome to Valhalla Legends Archive.
 

Getting started

Started by noarch, February 10, 2003, 04:20 PM

Previous topic - Next topic

noarch

Hello,
  I'd like to learn to program either the 80x86 (i think) windows/intel asm, or IA32 UNIX (FreeBSD in particular). I haven't fully researched either, just scrounged around the net looking for tutorials. On both all I've been able to come up with is nasm and a bunch of hello worlds that don't work. If someone could enlighten me to a website/good book on either of the two it would help me alot.
   noarch / metal

Skywing

#1
IA32 == Intel x86.  They're one and the same.

Anyways, maybe this reference might come in handy.

iago

#2
eew, ascii graphics :-)


The way I learned a lot was to write code in C, compile it with symbols, and use a debugger to see exactly what's happening.  
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*


Banana fanna fo fanna

#3
Under unix it's pretty easy, if you know C.

Get nasm and make a file that looks like this:

; Hello, world!

extern puts

[SECTION .text] ;this is the section where the code goes
main: ; main() method in C
push dword ptr mystring ; push an argument to the function
call puts ; call the function
add esp, 4 ; clean the arguments off of the stack

[SECTION .data] ; this is where initialized data goes
mystring db "Hello, world!",0 ; remember the 0 at the end, C strings end with a null

[SECTION .bss] ; uninitialized data, instead of using d* size specifiers, use res*, but we don't need them in this program.

Save that as hello.asm. Now run nasm -f elf hello.asm. Then, link with libc, using gcc -o hello hello.o

Calling a C function is easy, PUSH the arguments in reverse order (dword ptr for strings!) and CALL the function, then add esp, [number of bytes you pushed].

Grok

#4
How would you call a Java function from ASM?

j/k

CupHead

Iczelion's Win32ASM site is a good reference.  (http://win32asm.cjb.net)  His tutorials are an excellent way to become familiar with the Windows API and calling it from an assembly language program.  The (up/down)side to it is that his code is compiler specific (MASM) and uses its macros rather than pure assembly to demonstrate functions, so you'd be using some higher level syntax.  Also, there are a good deal of links from there to other assembly sites.

CupHead

If you do decide to go the way of Win32 stuff, this is a quick template I whipped up for MASM programs.  It's by and large based off of the Iczelion stuff, so this will help with going through those.  As is, it just creates an empty 300x200 window and processes the WM_DESTROY message.

;*****************
;** Always Here **
;*****************

.386
.model flat, stdcall
option casemap:none

;///////////////////////////////////////
;** End of essential compiler options **
;///////////////////////////////////////

;**************************************************************
;** Protocol declaration for entry-point of Windows programs **
;**************************************************************

WinMain proto :DWORD, :DWORD, :DWORD, :DWORD

;//////////////////////////////////////////////
;** End of pre-include protocol declarations **
;//////////////////////////////////////////////

;*******************
;** Include files **
;*******************

include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc

;//////////////////////////
;** End of include files **
;//////////////////////////

;*******************
;** Library files **
;*******************

includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib

;//////////////////////////
;** End of library files **
;//////////////////////////

;******************************************************
;** Protocol definitions dependent on included files **
;******************************************************


;//////////////////////////////////////
;** End of post-include declarations **
;//////////////////////////////////////

;*********************************
;** Constant Data Section (EQU) **
;*********************************

.const

;//////////////////////////////////
;** End of constant data section **
;//////////////////////////////////

;******************************
;** Initialized Data Section **
;******************************

.data
    ClassName       db      "MyWindowClass",0    ;Window class name
    AppName         db      "My Window Title",0    ;Window title

    RegisterFailed  db      "Window Registration Failed!",0
    CreateFailed    db      "Window Creation Failed!",0


;/////////////////////////////
;** End of initialized data **
;/////////////////////////////

;********************************
;** Uninitialized Data Section **
;********************************

.data?
    hInstance       HINSTANCE   ?   ;Handle to application instance
    CommandLine     LPSTR       ?   ;Pointer to command line string

;///////////////////////////////
;** End of uninitialized data **
;///////////////////////////////

;******************
;** Code Section **
;******************

.code
start:
    invoke  GetModuleHandle, NULL
    mov     hInstance, eax
    invoke  GetCommandLine
    mov     CommandLine, eax
    invoke  WinMain, hInstance, NULL, CommandLine, SW_SHOWDEFAULT
    invoke  ExitProcess, eax

WinMain proc hInst:HINSTANCE, hPrevInst:HINSTANCE, CmdLine:LPSTR, CmdShow:DWORD
    LOCAL   wc:WNDCLASSEX
    LOCAL   msg:MSG
    LOCAL   hwnd:HWND

    ;Fill in members of the WNDCLASSEX structure
    mov     wc.cbSize, SIZEOF WNDCLASSEX
    mov     wc.style, CS_HREDRAW or CS_VREDRAW
    mov     wc.lpfnWndProc, OFFSET WndProc
    mov     wc.cbClsExtra, NULL
    mov     wc.cbWndExtra, NULL
    push    hInst
    pop     wc.hInstance
    mov     wc.hbrBackground, COLOR_WINDOW+1
    mov     wc.lpszMenuName, NULL
    mov     wc.lpszClassName, OFFSET ClassName
    invoke  LoadIcon, NULL, IDI_APPLICATION
    mov     wc.hIcon, eax
    mov     wc.hIconSm, eax
    invoke  LoadCursor, NULL, IDC_ARROW
    mov     wc.hCursor, eax
    
    ;Register the class
    invoke  RegisterClassEx, ADDR wc
    test    eax, eax
    jz      Class_Registration_Failed
    
    ;Create the window
    invoke  CreateWindowEx, WS_EX_CLIENTEDGE, ADDR ClassName, \
            ADDR AppName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, \
            300, 200, NULL, NULL, hInst, NULL
    test    eax, eax
    jz      Window_Creation_Failed
    mov     hwnd, eax

    ;Show the window and update it.
    invoke  ShowWindow, hwnd, SW_SHOWNORMAL
    invoke  UpdateWindow, hwnd

    ;Message loop
    .WHILE TRUE
        invoke  GetMessage, ADDR msg, NULL, 0, 0
        .BREAK .IF (!eax)
        invoke  TranslateMessage, ADDR msg
        invoke  DispatchMessage, ADDR msg
    .ENDW
    mov     eax, msg.wParam
    ret

    Class_Registration_Failed:
        invoke  MessageBox, NULL, ADDR RegisterFailed, ADDR AppName, MB_OK
        invoke  ExitProcess, eax

    Window_Creation_Failed:
        invoke  MessageBox, NULL, ADDR CreateFailed, ADDR AppName, MB_OK
        invoke  ExitProcess, eax
WinMain endp

WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
    ;Process messages
    .IF uMsg==WM_DESTROY
        invoke  PostQuitMessage, NULL
    .ELSE
        invoke  DefWindowProc, hWnd, uMsg, wParam, lParam
        ret
    .ENDIF
    
    xor     eax, eax
    ret
WndProc endp

end start

;//////////////
;** End code **
;//////////////

Adron

#7
Why would you choose to write your program in some halfhighlevel language instead of either real assembler or real C? Note that you can use inline assembler to add whatever time critical code you want to a C program.

CupHead

Because the comparisons are based on the instructions.  Instead of .IF eax==0 it'd be test eax, eax: jz <label>  The "halfhighlevel language" as you call it improves readability by reducing the number of comparisons and labels required.  As long as you understand what it's really doing, I don't see why compiler macros like .IF are such a big deal.

Skywing

QuoteBecause the comparisons are based on the instructions.  Instead of .IF eax==0 it'd be test eax, eax: jz <label>  The "halfhighlevel language" as you call it improves readability by reducing the number of comparisons and labels required.  As long as you understand what it's really doing, I don't see why compiler macros like .IF are such a big deal.
The point is that you might as well use C for those types of things.  If you find yourself using all of these macro constructs to hide assembler, why not just use a real high level language and save yourself the trouble?

CupHead

#10
QuoteThe point is that you might as well use C for those types of things.  If you find yourself using all of these macro constructs to hide assembler, why not just use a real high level language and save yourself the trouble?

Because C.Ugliness >>>>> ASM.Ugliness?  It's a matter of personal preference and aesthetics.  Having hundreds of labels to handle every comparison is ridiculous, not to mention keeping track of them is a pain in the ass.  So why not use the macro constructs?  Using C would be fine if you wanted to program in C, but this is about assembly.

Banana fanna fo fanna

#11
Grok it's not too hard, just link it with the jni library and push a few extra parameters to a JNI function.

Banana fanna fo fanna

...Grok: call a .NET method from x86 asm plz ;)

EDIT: ytop

Adron

#13
QuoteBecause C.Ugliness >>>>> ASM.Ugliness?  It's a matter of personal preference and aesthetics.  Having hundreds of labels to handle every comparison is ridiculous, not to mention keeping track of them is a pain in the ass.  So why not use the macro constructs?  Using C would be fine if you wanted to program in C, but this is about assembly.


Sure, if you think asm looks better than C, and that's the reason you pick a language, go ahead. And let us all laugh at you while you're holding the programming language beauty competition ;)

Having lots of labels for comparisons is part of programming in assembly. Do the macros handle logical expressions too? (like .IF (a == 3 || a == 5) && b == 8 || b == 9 && a == 1)

I like programming in assembly, it's fun. To me though, the purpose of assembler has always been knowing exactly what instructions I am writing, and using that to write small and fast code. I don't see that happening when you're using macros for everything.


CupHead

You're completely overexaggerating.  There aren't macros in place for everything.  More importantly, why do you care?  It's still assembly, and if I like using macros, that's nice.  If you don't, good for you.  Also, I don't see how using a macro prevents small and fast code.  A macro is exactly what it is--a bit of code that gets inserted each time you use it.  Also, when you use a macro, you know exactly what instructions are going into it.  It's not like having to include a runtime library, it's a whole 3-4 lines each time you use one.  Seems to me you're just finding things to complain about.