Results 1 to 12 of 12
  1. #1
    B1ackAnge1's Avatar
    Join Date
    Aug 2009
    Gender
    male
    Posts
    455
    Reputation
    74
    Thanks
    344
    My Mood
    Cynical

    Hello World Anyone?

    Hello World in Assembly

    As is customary with almost every language the first thing people learn to do is how to print out a string of text (Usually being "Hello World!"). In higher level languages this is usually fairly easy to accomplish in relatively few lines of code. For instance in C++ one could write:
    Code:
    #include <iostream>
    using namespace std;
    
    int main()
    {
    	cout << "Hello World!" << endl;
    	return 0;
    }
    When it comes to assembly though, depending on the environment, a little more work is involved. If you were to disassemble the exe file generated by the above code you would see TONS of assembly code just to do this one simply task.

    Back in the 'old days' when MS-DOS reigned supreme and any assembly programming was done is 16 bit you had direct access to the 'MS-DOS API' which allowed you to easily deal with any of the hardware in a fairly direct matter.
    On the flip side you had to worry about the structure of your program in memory, which memory model to use etc etc.

    For instance a 16 Bit version of Hello World in Assembly would look like this:
    Code:
      .MODEL Small
      .STACK 100h
      .DATA
       msg db 'Hello World!',13,10,'$'
      .CODE
      start:
      mov ax, seg msg
      mov ds,ax
      mov ah, 09h
      lea dx, msg
      int 21h
      mov ax,4C00h
      int 21h
      end start
    It's definitely a little more cryptic. First the memory model gets set, a stack size gets defined. Then the data block sets the variables we will be using. Strings used this way need to be ended with the '$' symbol. The 13 and 10 values are \R and \N respectively which is a newline basically the same as the ENDL command in the C++ sample.
    The 'start:' label defines the start of the program. The next two lines make sure that the DataSegment actually points to the correct spot in memory.

    The core of the above is the Int 21h call. It basically takes a parameter in the AH register and does something with it. You can see it gets called twice. Once with 09h in AH and another with AX having the of 4C00h (thus AH = 4C). Basically when we use INT 21h with AH=09H we are telling it to print a string to the command line whose address pointer sits in the DX Register. As you can see this is basically the 'COUT' statement in the C++ Source

    The Second Int21 call basically says 'End of program and return what's in AL' which in this case is 0 so this is similar to the 'Return 0' statement in the C++ program.

    Ok this is all great, but in a sense this is all irrelevant for writing assembly now-adays against the Windows API. Everything Windows does is using the 'flat' memory model which means theoretically you have access to a full 4gb of ram, while under DOS it would only give you 16kb, hence the need for segments. Also Windows provides functionality for a lot of the functionality you used to have to talk directly for the hardware for. SO in a sense programming Assembly for windows makes it a little more 'high-level' than old-school MS-DOS Programming.

    So what if we now want to write a 32-bit Command-Line Version of 'Hello World' for Windows?
    The trick here is to not reinvent the wheel or go to 'low level' as your first instict may be, but to work against the provided Windows API with methods in the Windows DLLs. This code is for Masm32 (different assemblers may need slight tweaks etc)

    Code:
    .386
    .model flat, stdcall
    option casemap :none
    include \masm32\include\windows.inc
    include \masm32\include\kernel32.inc
    include \masm32\include\masm32.inc
    includelib \masm32\lib\kernel32.lib
    includelib \masm32\lib\masm32.lib
    
    .data
    HelloWorld db "Hello World!", 0
    
    .code
    start:
    invoke StdOut, addr HelloWorld
    invoke ExitProcess, 0
    end start
    Looking at this code from the top you'll see again some initialization (target platform is a 386, using the 'flat' memory model , standard calling convention and we're case-sensitive in our names). Then you see a bunch of 'include' and 'includelib' statements. If you're familiar with C++ this is very similar to including a Header File and telling the linker that when when building it should also include a specific LIB file. So in this instance we're including the Windows,Kernel32 and masm32 files. This will allow us to make windows sytem calls.

    Then we have the Data Segment again where we define our string (notice how this one is '0' terminated) after which we find the Code Segment. Instead of calling Interrupts as we did in the 16-bit sample we are now simply invoking existing Windows API Methods, namely: StdOut and Exit Process.
    As you can probably guess StdOut takes as a parameter the pointer to the 'Hello World' String and Exit Process will return '0' since that's what we're passing int.
    Notice that this is meant to be ran from within the command line otherwise it will just flash a window without altering the code to wait for input


    Ok, Great! But now what if we want to show an actual Dialog inside of windows? Well the only change we'd have to do is basically change where we call StdOut to something that shows a window. Windows provides a function called MessageBox which is just what we're looking for. This function though is provided in the user32.dll so we'll need to make sure to include this in our code.

    Looking at MSDN.microsof*****m we can find that the MessageBox functions takes the following parameters
    Code:
    int MessageBox(      
        HWND hWnd,
        LPCTSTR lpText,
        LPCTSTR lpCaption,
        UINT uType
    );
    Where hWnd is the window Owner - Not needed so set to NULL
    lpText is the pointer to the string to display: addr HelloWorld
    lpCaption is the Caption for the window, which we just set to the same text for convenience
    and uType is a enum which defines what buttons to show on the dialog, In this case just the 'OK' button.

    The finished code for this would then look like this:


    Code:
    .386
    .model flat, stdcall
    option casemap :none
    include \masm32\include\windows.inc
    include \masm32\include\kernel32.inc
    include \masm32\include\user32.inc
    includelib \masm32\lib\kernel32.lib
    includelib \masm32\lib\user32.lib
    .data
    HelloWorld db "Hello World!", 0
    .code
    start:
    invoke MessageBox, NULL, addr HelloWorld, addr HelloWorld, MB_OK
    invoke ExitProcess, 0
    end start

    Of course once this gets compiled when looking at it through a disassembler you will not see the code as nice as this, but that's for another time

    (ok hint : you'd see something more like this but without the nice readable variable names)
    Code:
    ...
    push MB_OK
    push offset HelloWorld
    push offset HelloWorld
    push NULL
    call MessageBoxA
    ...
    Last edited by B1ackAnge1; 10-22-2009 at 08:00 PM.

  2. The Following 4 Users Say Thank You to B1ackAnge1 For This Useful Post:

    Hell_Demon (10-26-2009),Void (12-06-2009),why06 (10-22-2009),zeco (11-01-2009)

  3. #2
    why06's Avatar
    Join Date
    Jul 2009
    Gender
    male
    Location
    IBM
    Posts
    4,304
    Reputation
    170
    Thanks
    2,203
    My Mood
    Flirty
    Holy crap! You wrote out the whole thing! Thanks a lot BA. Excellent explanation! May you live out the rest of your days in happiness!

    "Every gun that is made, every warship launched, every rocket fired signifies, in the final sense, a theft from those who hunger and are not fed, those who are cold and are not clothed. This world in arms is not spending money alone. It is spending the sweat of its laborers, the genius of its scientists, the hopes of its children. The cost of one modern heavy bomber is this: a modern brick school in more than 30 cities. It is two electric power plants, each serving a town of 60,000 population. It is two fine, fully equipped hospitals. It is some fifty miles of concrete pavement. We pay for a single fighter plane with a half million bushels of wheat. We pay for a single destroyer with new homes that could have housed more than 8,000 people. This is, I repeat, the best way of life to be found on the road the world has been taking. This is not a way of life at all, in any true sense. Under the cloud of threatening war, it is humanity hanging from a cross of iron."
    - Dwight D. Eisenhower

  4. #3
    B1ackAnge1's Avatar
    Join Date
    Aug 2009
    Gender
    male
    Posts
    455
    Reputation
    74
    Thanks
    344
    My Mood
    Cynical
    Ok taking this one step further :
    Now what if we wanted to make our own windows app with some controls on it? This means we need to do a few steps. First We need to create both WinMain and WndProc functions. WinMain is similar to your basic 'main' function in any old C++ program, and WndProc is processes all the messages that the window receives.

    Luckily in Masm32 you can make what are basically function prototypes and treat them like functions in C++ (though if you're using winasm it sorta looks like VB code down do the horizontal line across the screen.... yuck!). Also with the amount of processing you need to do Masm has some handy macros such as if else while break etc etc.

    Then to create the actual controls we use the CreateWindowEx Functions so it's really straightforward.
    Most of the code maps pretty true to how a C++ app would be written so I don't think I'll spend much time going through it line by line - besides.. i'm sure no one will even read this...

    Except of course for Why - which btw, See how even in Masm32 you can do higher level constructs of loops etc? Ditch the HLA man and just go this route



    Code:
    .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
    
    WinMain proto :DWORD, :DWORD, :DWORD, :DWORD
    
    .data
    ClassName db "WinClass", 0
    AppName db "Window Hello", 0
    TextBox db "edit",0
    Button db "button",0
    ButtonText db "Let's Do it!",0
    DisplayText db "Hello World of Windows!",0
    ButtonID WORD 1000h
    EditID WORD 1001h
    
    .data?
    hInstance HINSTANCE ?
    hEdit HWND ?
    hButton HWND ?
    
    .code
    start:
    invoke GetModuleHandle, NULL
    mov hInstance, eax
    invoke WinMain, hInstance, NULL, NULL, 0
    invoke ExitProcess, eax
    
    WinMain proc hInst:HINSTANCE, hPrevInst:HINSTANCE, CmdLine:LPSTR, CmdShow:DWORD
    local wc:WNDCLASSEX
    local msg:MSG
    local hwnd:HWND
    
    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 hInstance
    pop wc.hInstance
    mov wc.hbrBackground, COLOR_BACKGROUND
    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
    invoke RegisterClassEx, addr wc
    invoke CreateWindowEx, 0, addr ClassName, addr AppName, WS_OVERLAPPEDWINDOW or WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 300, 120, NULL,
    NULL, hInst, NULL
    mov hwnd, eax
    .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
    WinMain endp
    
    WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
    .if uMsg == WM_DESTROY
    	invoke PostQuitMessage, 0
    .elseif uMsg == WM_CREATE
    	invoke CreateWindowEx,NULL,addr Button,addr ButtonText,WS_CHILD or WS_VISIBLE or BS_DEFPUSHBUTTON, 70,35,80,30,hWnd,ButtonID,hInstance,NULL
    	mov hButton, eax
    	invoke CreateWindowEx,WS_EX_CLIENTEDGE,addr TextBox, NULL, WS_CHILD or WS_VISIBLE,10,10,200,20,hWnd,EditID,hInstance,NULL
    	mov hEdit, eax
    .elseif uMsg == WM_COMMAND
    	mov eax,wParam
    	.if ax == ButtonID
    		shr eax,10h
    		.if ax == BN_CLICKED
    			invoke SetWindowText,hEdit,addr DisplayText
    		.endif
    	.endif
    .else
    	invoke DefWindowProc, hWnd, uMsg, wParam, lParam
    ret
    .endif
    xor eax, eax
    ret
    WndProc endp
    
    end start
    Maybe for fun i'll rewrite this code to NOT use any macros like if/endif, invoke etc..

    Must say though that using the windows API like this sure takes away part of the 'mystery' of assembly programming when you were coding directly against the hardware with INTs etc..
    Last edited by B1ackAnge1; 10-23-2009 at 01:11 PM.

  5. #4
    why06's Avatar
    Join Date
    Jul 2009
    Gender
    male
    Location
    IBM
    Posts
    4,304
    Reputation
    170
    Thanks
    2,203
    My Mood
    Flirty
    Quote Originally Posted by B1ackAnge1 View Post
    Except of course for Why - which btw, See how even in Masm32 you can do higher level constructs of loops etc? Ditch the HLA man and just go this route
    Hmmmm... maybe your right. It's just that the guy wrote a 900 page book called the "Art of Assembly Language" that I'm using to learn by, but if it's teaching me the wrong stuff, maybe I should give it up. I think I'll look at some reviews before I make my final decision....

    And your right it does sort of make it look less cryptic... too less cryptic. I need to learn pure asm if I'm going to be able to reverse anything at all. So far theres just too much HLL stuff. But I have to say, that last code looked worse then HLA o_O?!

    "Every gun that is made, every warship launched, every rocket fired signifies, in the final sense, a theft from those who hunger and are not fed, those who are cold and are not clothed. This world in arms is not spending money alone. It is spending the sweat of its laborers, the genius of its scientists, the hopes of its children. The cost of one modern heavy bomber is this: a modern brick school in more than 30 cities. It is two electric power plants, each serving a town of 60,000 population. It is two fine, fully equipped hospitals. It is some fifty miles of concrete pavement. We pay for a single fighter plane with a half million bushels of wheat. We pay for a single destroyer with new homes that could have housed more than 8,000 people. This is, I repeat, the best way of life to be found on the road the world has been taking. This is not a way of life at all, in any true sense. Under the cloud of threatening war, it is humanity hanging from a cross of iron."
    - Dwight D. Eisenhower

  6. #5
    B1ackAnge1's Avatar
    Join Date
    Aug 2009
    Gender
    male
    Posts
    455
    Reputation
    74
    Thanks
    344
    My Mood
    Cynical
    Well stick with whatever works for you. I've found a good combo for ME in MASM32/WinAsm. Also have VStudio setup to build asm files but doesn't play as nice

    The thing with learning is write something like this, then run it through something like ollydbg and see what it turned it into. Since they're relatively small programs they should be easy to follow and it will show you what's going on behind the scenes so you can recognize things when you seem them 'in the field' so to speak. I rewrote your 'negate' program twice (once with using the invoke macro (nice and readable) and once without ) to show you the difference

  7. #6
    zeco's Avatar
    Join Date
    Jul 2009
    Gender
    male
    Location
    Canada
    Posts
    683
    Reputation
    12
    Thanks
    78
    My Mood
    Cynical
    This was awesome =). You are making me want to learn ASM more and more. But first i have to learn Java just for kicks :/

  8. #7
    B1ackAnge1's Avatar
    Join Date
    Aug 2009
    Gender
    male
    Posts
    455
    Reputation
    74
    Thanks
    344
    My Mood
    Cynical
    Wanna hear something really awesome?
    What i'm working on right now in ASM, for WHATEVER reason my AVG thinks is a Trojan! XD

  9. #8
    zeco's Avatar
    Join Date
    Jul 2009
    Gender
    male
    Location
    Canada
    Posts
    683
    Reputation
    12
    Thanks
    78
    My Mood
    Cynical
    Quote Originally Posted by B1ackAnge1 View Post
    Wanna hear something really awesome?
    What i'm working on right now in ASM, for WHATEVER reason my AVG thinks is a Trojan! XD
    The AI program from a little while ago came up as a virus when i tried to download it :/ And a program i made also came up as a virus for no reason. Don't remember which one tho. I wonder what criteria these antiviruses use to detect stuff. That's why i can't bother with 'em. Too many false positives. I don't need it anyway.

  10. #9
    why06's Avatar
    Join Date
    Jul 2009
    Gender
    male
    Location
    IBM
    Posts
    4,304
    Reputation
    170
    Thanks
    2,203
    My Mood
    Flirty
    Quote Originally Posted by zeco View Post
    The AI program from a little while ago came up as a virus when i tried to download it :/ And a program i made also came up as a virus for no reason. Don't remember which one tho. I wonder what criteria these antiviruses use to detect stuff. That's why i can't bother with 'em. Too many false positives. I don't need it anyway.
    Well you don't really have to worry unless your downloading a lot of sketchy files. The only other way to get a virus on your system is probably if someone attacked you directly, which no antivirus is gonna stop anyway... =/

    "Every gun that is made, every warship launched, every rocket fired signifies, in the final sense, a theft from those who hunger and are not fed, those who are cold and are not clothed. This world in arms is not spending money alone. It is spending the sweat of its laborers, the genius of its scientists, the hopes of its children. The cost of one modern heavy bomber is this: a modern brick school in more than 30 cities. It is two electric power plants, each serving a town of 60,000 population. It is two fine, fully equipped hospitals. It is some fifty miles of concrete pavement. We pay for a single fighter plane with a half million bushels of wheat. We pay for a single destroyer with new homes that could have housed more than 8,000 people. This is, I repeat, the best way of life to be found on the road the world has been taking. This is not a way of life at all, in any true sense. Under the cloud of threatening war, it is humanity hanging from a cross of iron."
    - Dwight D. Eisenhower

  11. #10
    Dark_Goliath's Avatar
    Join Date
    Nov 2009
    Gender
    male
    Location
    Romania
    Posts
    308
    Reputation
    10
    Thanks
    28
    My Mood
    Sad
    Hmmm very nice but the first code need a
    Code:
    system("pause");
    before
    Code:
    return 0;
    if u don't have that the console app will flash very very quicly on ur screen and u will can't see nothing

  12. #11
    B1ackAnge1's Avatar
    Join Date
    Aug 2009
    Gender
    male
    Posts
    455
    Reputation
    74
    Thanks
    344
    My Mood
    Cynical
    Yeah thanks, however:

    a) the cpp code was a mere illustration and comparison against assembly source to show how few lines are required in higher level languages and not meant to be compiled/run.

    b) It's a console app, so running it from the console which is how it's intended to run wouldn't have the issue of it closing after running. (though I'm fairly sure most people on this board don't know how to work in the console)

    c) system("Pause") is evil. Getch() or something equivalent would be better suited if one were to insist on running it by double clicking it.

    d) see a

    but hey glad someone actually read this section for change

  13. #12
    Dark_Goliath's Avatar
    Join Date
    Nov 2009
    Gender
    male
    Location
    Romania
    Posts
    308
    Reputation
    10
    Thanks
    28
    My Mood
    Sad
    Yep i agree with u but i use
    Code:
    system("pause");

Similar Threads

  1. Hello World Disassembly
    By why06 in forum Assembly
    Replies: 15
    Last Post: 01-21-2010, 09:21 AM
  2. New o C++? Simple Hello world (Added a little extra)
    By headsup in forum C++/C Programming
    Replies: 10
    Last Post: 11-09-2009, 06:00 PM
  3. A closer look at Hello World App.
    By headsup in forum Java
    Replies: 5
    Last Post: 10-24-2009, 12:25 AM
  4. hello, could anyone make me a cool avatar?
    By ltjustas1 in forum Help & Requests
    Replies: 4
    Last Post: 09-20-2009, 11:53 AM
  5. [C++]Hello World; Your first C++ Program
    By Mr. Bond in forum Programming Tutorials
    Replies: 3
    Last Post: 02-09-2009, 08:53 AM

Tags for this Thread