project A DOS® Server In a Virtual Machine

An Assembly Language

This article is primarily dedicated to an Assembler for Linux.
I chose The Netwide Assembler (also known as "NASM"). But I've been confronted with difficulties since then.
I'm scarce of knowledge of programming in the Assembly language under Linux.

Table Of Contents:




"Hello World" under DOS

  NASM TASM
COM ; This example is compiled into a COM
; It is written in NASM.
; Copyleft 2014 Artem Efremov

   org 100h

section .text
start:
   mov AH, 09h
   lea DX, [CS:msg]
   int 21h

   mov AX, 4C00h; Errorlevel = 0
   int 21h

section .data
   msg DB "Hello World", 0Dh, 0Ah, "$"

section .bss
   ; uninitialized data here
; This example is compiled into a COM
; It is written in TASM.
; Copyleft 2014 Artem Efremov

.model tiny
code segment
assume CS:code, DS:code
   org 100h


start:
   mov AH, 09h
   lea DX, [CS:msg]
   int 21h

   mov AX, 4C00h; Errorlevel = 0
   int 21h


   msg DB "Hello World", 0Dh, 0Ah, "$"
code ends
end start
EXE ; This example is compiled into an EXE
; It is written in NASM.
; Copyleft 2014 Artem Efremov

segment code

..start:
   mov AX, data
   mov DS, AX
;   mov AX, stack
;   mov SS, AX
;   mov SP, stacktop

   lea DX, [DS:msg]
   mov AH, 09h
   int 21h

   mov AX, 4C00h
   int 21h

segment data

msg:
   DB "Hello World", 0Dh, 0Ah, "$"

segment stack stack
       resb 256
stacktop:
; This example is compiled into an EXE
; It is written in TASM.
; Copyleft 2014 Artem Efremov

text segment
   assume CS:text, DS:data

start:
   mov AX, data
   mov DS, AX
   lea DX, [DS:msg]
   mov AH, 09h
   int 21h

   mov AX, 4C00h; Errorlevel = 0
   int 21h

text ends

data segment

   msg DB "Hello World", 0Dh, 0Ah, "$"

data ends

stk segment stack
   DB 256 DUP(0)
ends

end start

"Hello World" under Linux

; http://www.int80h.org/bsdasm/#system-calls
; nasm -f elf hello2.asm && ld -s -o hello2 hello2.o
%include "system.inc"; Asmutils is required

section .data
hello DB "Hello, World!", 0Ah
hbytes EQU hello

section .text
global _start
_start:
   push dword hbytes
   push dword hello
   push dword stdout
   sys.write

   push dword 0
   sys.exit


nasm -f elf hello.asm && ld -s -o hello hello.o

[Download Asmutils]

An Input under Linux

; This example demonstrates using Linux/i386 system calls by example of a user's input
; Written in NASM.
; by Artem V. Efremov (also known as "Nikodim")
;
; Some useful information is available at:
; http://www.ibm.com/developerworks/ru/library/l-gas-nasm/index.html
; http://www.nasm.us
; http://www.unusedino.de/linuxassembly/syscall.html
; parameters: EBX, ECX, EDX, ESI, EDI (for Linux kernel, ver. 2.4+), EBP
; returned code: EAX


buffersize EQU 1024; the buffer's size (in bytes)

section .text
global _start
_start:

   lea ECX, [DS:welcome]
   mov EDX, welcome_len
   push EDX; parameter passing
   push ECX; parameter passing
   call NEAR printIt
   pop ECX
   pop EDX

begin:
   mov AL, 0; ASCII(0)
   push AX; parameter passing
   call NEAR zerofilling; initializing the buffer
   pop AX

   lea ECX, [DS:prompt]
   mov EDX, prompt_len
   push EDX; parameter passing
   push ECX; parameter passing
   call NEAR printIt
   pop ECX
   pop EDX

; sys_read: ssize_t sys_read(unsigned int fd, char * buf, size_t count)
   mov EAX, 3; sys_read
   mov EBX, 1
   lea ECX, [DS:buffer]; offset
   mov EDX, buffer_len
   int 80h

   call NEAR buffer_reckoning; reckoning the actual buffer's length

   lea ECX, [DS:msgbefore]
   mov EDX, msgbefore_len
   push EDX; parameter passing
   push ECX; parameter passing
   call NEAR printIt
   pop ECX
   pop EDX

   lea ECX, [DS:buffer]
   mov EDX, [DS:buffer_act_len]
   push EDX; parameter passing
   push ECX; parameter passing
   call NEAR printIt
   pop ECX
   pop EDX

   lea ECX, [DS:endl]
   mov EDX, endl_len
   push EDX; parameter passing
   push ECX; parameter passing
   call NEAR printIt
   pop ECX
   pop EDX

; the "say" command
   lea EDI, [DS:cmd_say]; the command's offset
   mov EAX, cmd_say_len
   push EAX
   push EDI
   call NEAR check_for_equality
   pop EDI
   pop EAX
   cmp ECX, 0; comparing whether the two strings are equal to each other
   jnz next_check_02

   lea ECX, [DS:say]
   mov EDX, say_len
   push EDX; parameter passing
   push ECX; parameter passing
   call NEAR printIt
   pop ECX
   pop EDX

next_check_02:

; the "exit" command
   lea EDI, [DS:cmd_exit]; the command's offset
   mov EAX, cmd_exit_len
   push EAX
   push EDI
   call NEAR check_for_equality
   pop EDI
   pop EAX
   cmp ECX, 0; comparing whether the two strings are equal to each other
   jnz begin; returning if not "exit"

; a quit message
   lea ECX, [DS:endline]
   mov EDX, endline_len
   push EDX; parameter passing
   push ECX; parameter passing
   call NEAR printIt
   pop ECX
   pop EDX

; sys_exit: int sys_exit(int status)
   mov EAX, 1; sys_exit
   mov EBX, 0; status = 0
   int 80h

printIt:
   push EBP
   push ECX
   push EDX
   push EAX
   push EBX

   mov EBP, ESP

; sys_write: ssize_t sys_write(unsigned int fd, const char * buf, size_t count)
   mov EAX, 4; sys_write
   mov EBX, 1
   mov ECX, [SS:EBP + 4 + 4 + 4 + 4 + 4 + 4]; EBX + EAX + EDX + ECX + EBP + EIP
   mov EDX, [SS:EBP + 4 + 4 + 4 + 4 + 4 + 4 + 4]; EBX + EAX + EDX + ECX + EBP + EIP
   int 80h

   pop EBX
   pop EAX
   pop EDX
   pop ECX
   pop EBP
   retn


zerofilling:
; zerofilling
   push EBP
   push ECX
   push EDX
   push AX

   mov EBP, ESP
   mov AX, [SS:EBP + 2 + 4 + 4 + 4 + 4]; AX + EDX + ECX + EBP + EIP
   mov ECX, buffer_len; setting the counter
   lea EDX, [DS:buffer]
loop_01:
   mov BYTE [DS:EDX + ECX - 1], AL; ASCII(0)
   loop loop_01

   pop AX
   pop EDX
   pop ECX
   pop EBP
   retn

buffer_reckoning:
   push ECX
   push ESI
   push AX
   pushf

; reckoning the actual buffer's length
   cld; clearing the DF flag (forward direction)
   mov ECX, 0; ECX = 0
   lea ESI, [DS:buffer]
loop_02:
   lodsb
   cmp AL, 0
   jz next_step_01
   inc ECX; ECX++
   jmp SHORT loop_02

next_step_01:
   mov [DS:buffer_act_len], ECX

   popf
   pop AX
   pop ESI
   pop ECX
   retn


check_for_equality:
; checking for a command in the list
; (returns: ECX = 0 if true; otherwise, false)
   push EBP
   pushfd
   push ESI
   push EDI

   mov EBP, ESP

   cld
   mov CX, DS
   mov ES, CX
   lea ESI, [DS:buffer]; the buffer: [DS:ESI]
   mov EDI, [SS:EBP + 4 + 4 + 4 + 4 + 4]; the command's offset: [ES:EDI]
   mov ECX, [SS:EBP + 4 + 4 + 4 + 4 + 4 + 4]
   repe cmpsb; comparing the two strings

   pop EDI
   pop ESI
   popfd
   pop EBP
   retn



section .data

welcome: DB 0Dh, 0Ah, "*** An Input Utility for Linux/i386", 0Ah
DB "This has been written by Artem V. Efremov (also known as 'Nikodim') in The Netwide Assembler.", 0Ah
DB "http://vm.ru54.com/asm/", 0Ah
DB "You may use the program for evaluation purpose, modify the code.", 0Ah
DB "Type 'exit' to quit. Type 'say' to say 'Hello' everybody. Type something just for fun.", 0Dh, 0Ah
welcome_len EQU $ - welcome

prompt: DB 0Dh, 0Ah, "Type something> "
prompt_len EQU $ - prompt

endl: DB 0Dh, 0Ah; "\n"
endl_len EQU $ - endl

endline: DB 0Dh, 0Ah, "Exiting...", 0Dh, 0Ah
endline_len EQU $ - endline

msgbefore: DB 0Dh, 0Ah, "You have typed: "
msgbefore_len EQU $ - msgbefore

buffer_act_len: DD 0; actual length of the buffer
buffer: TIMES buffersize DB "E"; buffer
buffer_len EQU $ - buffer
DB 0; ASCII(0): the end of the buffer

; commands:

cmd_exit: DB "exit"
cmd_exit_len EQU $ - cmd_exit

cmd_say: DB "say"
cmd_say_len EQU $ - cmd_say

say: DB 0Dh, 0Ah, "Hello there! :)", 0Dh, 0Ah
say_len EQU $ - say

section .bss
   ; uninitialized data

section .stack

Reboot

; This program reboots a Linux/i386 system for no reason.
; Written in NASM.
; by Artem V. Efremov (also known as "Nikodim")
;
; kernel/sys.c
; int reboot(int magic1, int magic2, int cmd, void *arg);
;
; Some useful information is available at:
; http://man.he.net/man2/reboot
; http://www.ibm.com/developerworks/ru/library/l-gas-nasm/index.html
; http://www.nasm.us
; http://www.unusedino.de/linuxassembly/syscall.html
; parameters: EBX, ECX, EDX, ESI, EDI (for Linux kernel, ver. 2.4+), EBP
; returned code: EAX

section .text
global _start
_start:

   call NEAR reboot

; sys_exit: int sys_exit(int status)
   mov EAX, 1; sys_exit
   mov EBX, 0; status = 0
   int 80h

reboot:
   push EAX
   push EBX
   push ECX
   push EDX
   push ESI

; http://man.he.net/man2/reboot
; int reboot(int magic1, int magic2, int cmd, void *arg);
   mov EAX, 88; sys_reboot
   mov EBX, 0xfee1dead; magic1 = 0xfee1dead (LINUX_REBOOT_MAGIC1)
   mov ECX, 672274793; magic2 = 672274793 (LINUX_REBOOT_MAGIC2)
   mov EDX, 0x1234567; cmd = 0x1234567 (LINUX_REBOOT_CMD_RESTART)
   mov ESI, 0; *arg = 0
   int 80h

   pop ESI
   pop EDX
   pop ECX
   pop EBX
   pop EAX
   retn



section .data


section .bss
   ; uninitialized data

section .stack

Useful Links