Showing posts with label assembly. Show all posts
Showing posts with label assembly. Show all posts

Thursday, July 18, 2013

Assembly Tip

It look like we should not use memory address directly in Assembly. Let's take a look at following example:

movl $0xA9000, %ebx
rdtsc
movl %eax, (%ebx)
movl %edx, 4(%ebx)

It stores the TSC value to memory location 0xA9000.
If I use the memory location directly in the assembly, the code willl not work. 

rdtsc
movl %eax, 0xA9000
movl %edx, 0xA9004




Thursday, May 2, 2013

Access x86 debug register DR0 to DR7

x86 debug register allow access in ring0 or SMM.

On Windows, you may want to write a device driver to run your code
On Linux, you need to write a kernel module to run your code

This sample code sets the DR0 to value 0x4013c8, which is an entry point of a program. It also sets the DR7 to value 0x401, which is to enable local breakpoint of DR0.

Tested code is following:


u32 dr0_RD=0xff;
u32 dr7_RD=0xff;



asm __volatile__ (
"mov %%dr0, %0\n"
"mov %%dr7, %1\n"
:"=r"(dr0_RD), "=r"(dr7_RD)
);
printk("\ndr0_RD is: %x\ndr7_RD is: %x\n", dr0_RD, dr7_RD);


asm __volatile__ (
"movl $0x401, %eax\n"
"movl %eax, %dr7\n"
"movl $0x4013c8, %eax\n"
"movl %eax, %dr0\n"
);

asm __volatile__ (
"mov %%dr0, %0\n"
"mov %%dr7, %1\n"
:"=r"(dr0_RD), "=r"(dr7_RD)
);


printk("\ndr0_RD is: %x\ndr7_RD is: %x\n", dr0_RD, dr7_RD);


Notes about inline gcc assembly

For the block of code in red, I cannot do movl $0x401, %dr4; Additionally, I cannot define a variable u32 dr7 =0x401, and pass it to the inline gcc assembly, "movl %0, %%dr7\n":"=r"(dr7)

Additionally, if there is a paramater passing, all of the register need to use two percent. Otherwise  compile error will generates.

Friday, May 18, 2012

Reference: Convert Assembly to Opcode

http://ref.x86asm.net/

Modify Executable in Windows

1. Download Hex Editor: HxD
http://download.cnet.com/HxD-Hex-Editor/3000-2352_4-10891068.html

2. Open the Executable by using HxD

3. Go the executable place you want to modify
For example (nasm format) :
66 BA 2F 05 : mov dx, 0x52f
66 EE : out dx, al

Thursday, May 17, 2012

Assembly in Windows

1. Compiler: MASM 
download: http://www.masm32.com/
install it
it has an masm editor
it use NASM assembly, please use pcasm for reference
http://www.drpaulcarter.com/pcasm/
But it doesn't have the IO instruction in the book


2. Start with hello world program

include \masm32\include\masm32rt.inc  

.data
MyTitle db "ASM is Fun!",0
MyText db "I hope you're learning!",0
.codestart:
push 0
push offset MyTitle
push offset MyTextpush 0
call MessageBoxA
call ExitProcess
end start



URL: http://computertech.createmybb3.com/showthread.php?tid=105
http://www.youtube.com/watch?v=gklpZIVuTBY



3. Write your own program

.386
.model flat,stdcall
.code
start
mov dx, 1327
out dx, ax
end start



This program write port 0x52f It looks like MASM cannot use hex because I get compile error.



4. Run the Program 

AllowIo.exe WritePort.exe /a
write to port in Windows, please see my another article
http://fengweizhang.blogspot.com/2012/04/user-program-write-to-io-ports-on.html



Saturday, March 24, 2012

translate assembly to machine code

On Linux Machine:
1. write your assembly code into code.S
2. compile your code: $ gcc -c code.S
3. use objdump to see the binarry code: $ objdump -d code.o 

Monday, December 20, 2010

print out ebp, esp, eax by gcc inline assembly

Here is the code:

#include <stdio.h>
int main(int argc, char* argv[])
{
    unsigned esp, ebp, eax, ebx, ecx, edx;

    asm(
        "movl %%esp, %0;"
        "movl %%ebp, %1;"
        "movl %%eax, %2;"
        "movl %%ebx, %3;"
        "movl %%ecx, %4;"
        "movl %%edx, %5;"
        :"=r"(esp), "=r"(ebp), "=r"(eax), "=r"(ebx), "=r"(ecx), "=r"(edx)
        );
    printf("esp is: %x\n", esp);
    printf("ebp is: %x\n", ebp);   
    printf("eax is: %x\n", eax);
    printf("ebx is: %x\n", ebx);
    printf("ecx is: %x\n", ecx);   
    printf("edx is: %x\n", edx); 

    return 1;
}

GCC inline assembly syntax:
asm(
//assembly code;
: output operand
: input operand
: registers

"=r" I could use any registers for caculation. "=" means write only
"a": I could use %eax for caculation.

Here is the list:
please see Register operand constraint
http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html



)

Tuesday, November 16, 2010

assembly tutorial

http://docs.sun.com/app/docs/doc/817-5477/ennab?a=view

 There are two types of lables: symbolic and numeric.

Symbolic Labels

A symbolic label consists of an identifier (or symbol) followed by a colon (:) (ASCII 0x3A). Symbolic labels must be defined only once. Symbolic labels have global scope and appear in the object file's symbol table.
Symbolic labels with identifiers beginning with a period (.) (ASCII 0x2E) are considered to have local scope and are not included in the object file's symbol table.

Numeric Labels

A numeric label consists of a single digit in the range zero (0) through nine (9) followed by a colon (:). Numeric labels are used only for local reference and are not included in the object file's symbol table. Numeric labels have limited scope and can be redefined repeatedly.
When a numeric label is used as a reference (as an instruction operand, for example), the suffixes b (“backward”) or f (“forward”) should be added to the numeric label. For numeric label N, the reference Nb refers to the nearest label N defined before the reference, and the reference Nf refers to the nearest label N defined after the reference. The following example illustrates the use of numeric labels:
1:          / define numeric label "1"
one:        / define symbolic label "one"

/ ... assembler code ...

jmp   1f    / jump to first numeric label "1" defined
            / after this instruction
            / (this reference is equivalent to label "two")

jmp   1b    / jump to last numeric label "1" defined
            / before this instruction
            / (this reference is equivalent to label "one")

1:          / redefine label "1"
two:        / define symbolic label "two"

jmp   1b    / jump to last numeric label "1" defined
            / before this instruction
            / (this reference is equivalent to label "two")

Operands
An x86 instruction can have zero to three operands. Operands are separated by commas (,) (ASCII 0x2C). For instructions with two operands, the first (lefthand) operand is the source operand, and the second (righthand) operand is the destination operand (that is, source->destination).

Note – The Intel assembler uses the opposite order (destination<-source) for operands.

Operands can be immediate (that is, constant expressions that evaluate to an inline value), register (a value in the processor number registers), or memory (a value stored in memory). An indirect operand contains the address of the actual operand value. Indirect operands are specified by prefixing the operand with an asterisk (*) (ASCII 0x2A). Only jump and call instructions can use indirect operands.
  • Immediate operands are prefixed with a dollar sign ($) (ASCII 0x24)
  • Register names are prefixed with a percent sign (%) (ASCII 0x25)
  • Memory operands are specified either by the name of a variable or by a register that contains the address of a variable. A variable name implies the address of a variable and instructs the computer to reference the contents of memory at that address. Memory references have the following syntax:segment:offset(base, index, scale).
    • Segment is any of the x86 architecture segment registers. Segment is optional: if specified, it must be separated from offset by a colon (:). If segment is omitted, the value of %ds (the default segment register) is assumed.
    • Offset is the displacement from segment of the desired memory value. Offset is optional.
    • Base and index can be any of the general 32–bit number registers.
    • Scale is a factor by which index is to be multipled before being added to base to specify the address of the operand. Scale can have the value of 1, 2, 4, or 8. If scale is not specified, the default value is 1.
    Some examples of memory addresses are:
    movl var, %eax
    Move the contents of memory location var into number register %eax.
    movl %cs:var, %eax
    Move the contents of memory location var in the code segment (register %cs) into number register %eax.
    movl $var, %eax
    Move the address of var into number register %eax.
    movl array_base(%esi), %eax
    Add the address of memory location array_base to the contents of number register %esi to determine an address in memory. Move the contents of this address into number register %eax.
    movl (%ebx, %esi, 4), %eax
    Multiply the contents of number register %esi by 4 and add the result to the contents of number register %ebx to produce a memory reference. Move the contents of this memory location into number register %eax.
    movl struct_base(%ebx, %esi, 4), %eax
    Multiply the contents of number register %esi by 4, add the result to the contents of number register %ebx, and add the result to the address of struct_base to produce an address. Move the contents of this address into number register %eax.


Assembler Directives

Directives are commands that are part of the assembler syntax but are not related to the x86 processor instruction set. All assembler directives begin with a period (.) (ASCII 0x2E).
.align integer, pad
The .align directive causes the next data generated to be aligned modulo integer bytes. Integer must be a positive integer expression and must be a power of 2. If specified, pad is an integer bye value used for padding. The default value of pad for the text section is 0x90 (nop); for other sections, the default value of pad is zero (0).
.bss
The .bss directive changes the current section to .bss.
.bss symbol, integer
Define symbol in the .bss section and add integer bytes to the value of the location counter for .bss. When issued with arguments, the .bss directive does not change the current section to .bss. Integer must be positive.
.
.globl symbol1, symbol2, ..., symbolN
The .globl directive declares each symbol in the list to be global. Each symbol is either defined externally or defined in the input file and accessible in other files. Default bindings for the symbol are overridden. A global symbol definition in one file satisfies an undefined reference to the same global symbol in another file. Multiple definitions of a defined global symbol are not allowed. If a defined global symbol has more than one definition, an error occurs. The .globl directive only declares the symbol to be global in scope, it does not define the symbol.
.group group, section, #comdat
The .group directive adds section to a COMDAT group. Refer to COMDAT Section in Linker and Libraries Guide for additional information about COMDAT.
.section section, attributes
The .section directive makes section the current section. If section does not exist, a new section with the specified name and attributes is created. If section is a non-reserved section, attributes must be included the first time section is specified by the .section directive.

segment selectors, segmentation registers, segment descirptors

*****************
Protected Mode
*****************
Segment Selector: 16 bits field.
15-3: index of entries in gdt or in ldt
2: table indicator (0 descriptor stores in gdt; 1 descriptor stores in ldt )
1-0: requester privilege level(in CS register, it is current privilege level called CPL, 0 denotes kernel mode, 3 denotes user mode.)

Segmentation Registers: is to hold segment selectors, these registers are called cs, ss, ds, es, fs and gs.
cs: The code segment registers, which points to a segment containing program insturction
ss: The stack segment registers, which points to a segment containing the current program stack
ds: The data segment registers, which points to a segment containing global and static data

Segment Descriptor: 8 bytes, it describes the segment characteristics.
segment descirptor are stored either in the global descriptors table (GDT) or in local descriptors table (LDT).
Remember Descriptor privilege level (DPL) is in segment descriptor. we need to check CPL < DPL, then we could access that memory.


Translating a logical address to linear address by using SEGMENTATION UNIT

index * 8 + (base address of gdt or ldt) + (32 bits offset) = linear address


please see understanding Linux kernel chapter 2. page 41 for more information.

*****************
Real Mode

*****************
In real mode, the CS is different from CS in protected mode, It stores physical address
like instruction ljmp 0xa000, 0x0000
it will set the cs = 0xa000, and eip =0x0000
translating to physical address is: 
so the instruction will be executing is: cs * 16 + eip = 0xa0000
remember, there is no global descriptor table in real mode.

Monday, November 15, 2010

ljmp, outb

ljmp 0xa000, 0x0000
this instruction will set the CS to 0xa000 and set the EIP 0x0000. Bascially, it will start to execute code at location CS*16 + EIP = 0xa0000

in real mode, if you write:
jmp 0xa0000, it won't work, it will have compile errors. because there is only 16 bits.

see first part is CS, second part is EIP
http://docs.sun.com/app/docs/doc/805-4693/6j4emccqq?l=ru&a=view

please also see wiki jmp instruction
http://en.wikipedia.org/wiki/JMP_%28x86_instruction%29


outb %al, (%dx)
outb %al, %dx
outb %al, 0x80

oub instruction only could out to value stores at dx, or immeidate values.
please see more inforamtion from
"Intel Architecture Software Developer's Manual, Volume 2: Instruction Set Reference Manual

Friday, November 12, 2010

GAS v.s. NASM

AT&T GCC GAS
http://sig9.com/articles/att-syntax
http://en.wikibooks.org/wiki/X86_Assembly/GAS_Syntax



NASM, X86, Intel
http://www.drpaulcarter.com/pcasm/

Now we saw some of the major differences between Intel syntax and AT&T syntax. I’ve wrote only a few of them. For a complete information, refer to GNU Assembler documentations. Now we’ll look at some examples for better understanding.

+------------------------------+------------------------------------+
|       Intel Code             |      AT&T Code                     |
+------------------------------+------------------------------------+
| mov     eax,1                |  movl    $1,%eax                   |   
| mov     ebx,0ffh             |  movl    $0xff,%ebx                |   
| int     80h                  |  int     $0x80                     |   
| mov     ebx, eax             |  movl    %eax, %ebx                |
| mov     eax,[ecx]            |  movl    (%ecx),%eax               |
| mov     eax,[ebx+3]          |  movl    3(%ebx),%eax              | 
| mov     eax,[ebx+20h]        |  movl    0x20(%ebx),%eax           |
| add     eax,[ebx+ecx*2h]     |  addl    (%ebx,%ecx,0x2),%eax      |
| lea     eax,[ebx+ecx]        |  leal    (%ebx,%ecx),%eax          |
| sub     eax,[ebx+ecx*4h-20h] |  subl    -0x20(%ebx,%ecx,0x4),%eax |

Monday, November 8, 2010

x86-64 assembly

I am going to address the difference between IA32 and x86-64 ATT assemly.
if you want to see more details, please see lecture 13 of:
http://www.cs.gmu.edu/~setia/cs367/slides/index.html

EBP will not be the special register.
ESP will be constant.
pass arguments by using registers(MAX = 6).
allocate local variables aromatically at the function call.

Thursday, November 4, 2010

AT&T assembly examples

In this blog, I am going to give some example of assembly language.

movb  $0x11, 0xa0000 // this is going to write 1 byte 0x11 to memory 0xa0000
movw $0xa000, %dx // this is going move 2 bytes 0xa000 to register dx
movl  $0x0000ffcc, %eax // this is going to move 4 bytes to register eax

/*write some ports*/
movb $0x11, %al
movw $0x80, %dx
outb %al, %dx
// this is going to write a single byte at the port 0x80
// us dx to store the port number seems like the convention
// if it is in: inb %dx, %al // read from port %dx, and store it in %al


/*write to serial port 0x3f8*/
movb $0x11, %al
movw $0x3f8, %dx
outb %al, %dx
// this code if you don't move serial port number to dx, just using outb %al, $3f8
// this will not work. I don't know why, but I think I have tested.

/*use a loop to do copy*/

movl $0xa0000, %eax
movl $smm_handler_start, %ebx
movl $smm_handler_end, %ecx
subl $smm_handler_start, %ecx
mylabel:
             movb (%ebx), %dl
             movb %dl, (%eax)
             inc %eax
             inc %ebx
             loop mylabel

// this code is going to copy content from [smm_hanlder_start, smm_handler_end) to memory address 0xa0000. smm_handler_start and smm_handler_end are label in another .S file. and they need to declare it as .global, and current file need to declare it as .extern. the number of times the loop will execute is the value at ecx. but in C is different. For example:
foo.S
.global smm_handler_start

smm_handler_start:
...
...


bar.c
extern uint_8 smm_handler_start
// if you want to get the address of smm_hanlder_start
// you need to use it like: &smm_hanlder_start (= $smm_hanlder_start in asm)

Tuesday, October 19, 2010

inline gcc assembly

http://wiki.osdev.org/Inline_Assembly/Examples

http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html

E.G.


int a=10, b;
        asm ("movl %1, %%eax; 
              movl %%eax, %0;"
             :"=r"(b)        /* output */
             :"r"(a)         /* input */
             :"%eax"         /* clobbered register */
             );       


Above code will have compile errors, but if you put assembly code line2 and line3 together, it will compile. Or you could change it to:


int a=10, b;
        asm ("movl %1, %%eax;" 
             "movl %%eax, %0;"
             :"=r"(b)        /* output */
             :"r"(a)         /* input */
             :"%eax"         /* clobbered register */
             );       

This time, it will work.


Explaining:

Here what we did is we made the value of ’b’ equal to that of ’a’ using assembly instructions. Some points of interest are:

  • "b" is the output operand, referred to by %0 and "a" is the input operand, referred to by %1.
  • "r" is a constraint on the operands. We’ll see constraints in detail later. For the time being, "r" says to GCC to use any register for storing the operands. output operand constraint should have a constraint modifier "=". And this modifier says that it is the output operand and is write-only.
  • There are two %’s prefixed to the register name. This helps GCC to distinguish between the operands and registers. operands have a single % as prefix.
  • The clobbered register %eax after the third colon tells GCC that the value of %eax is to be modified inside "asm", so GCC won’t use this register to store any other value.

When the execution of "asm" is complete, "b" will reflect the updated value, as it is specified as an output operand. In other words, the change made to "b" inside "asm" is supposed to be reflected outside the "asm".

Now we may look each field in detail.

Wednesday, October 6, 2010

C calling conventaion && active record && stack

The fast way to understand C calling convention is to write a C program and compile it into assembly, and understand the assembly code. For exmaple:
## test.c ##
#include <stdio.h>
int sum(int a, int b)
{
  int c;
  c= a+b;
  return c;


}
int main(void)
{
  int a = 1;
  int b = 2;
  sum(a, b);
  return 1;
}




## compile ##
gcc -S test.c


## assembly ##
    .file    "test.c"
    .text
.globl sum
    .type    sum, @function
sum:
    pushl    %ebp                             // save previous ebp, which is ebp in main()
    movl    %esp, %ebp                   // set the new ebp of sum() = current esp value
    subl    $16, %esp                       // esp = esp -16
    movl    12(%ebp), %eax            // *(%ebp+12), this is value b, put in eax
    movl    8(%ebp), %edx              // put value a into edx
    leal    (%edx,%eax), %eax        //
    movl    %eax, -4(%ebp)             //*(ebp-4): this is local variable c.
    movl    -4(%ebp), %eax            // put c into eax again, becase return value in eax
    leave                                       // movl %ebp, %esp; pop %ebp
                                                   // set the value of esp = the value of ebp, pop the 
                                                   // first element in stack, which is the saved ebp    ret                                        // pop %eip, pop the return address, and save to eip
    .size    sum, .-sum
.globl main
    .type    main, @function
main:
    pushl    %ebp                           // save ebp
    movl    %esp, %ebp                 // the value in ebp reigster = the value in esp reg
    subl    $24, %esp                     // esp = esp -24


/*push the local variables into stack*/
    movl    $1, -4(%ebp)                // put value 1 into stack. this is local variable.
                                                    // ebp always point to the top of local variables
    movl    $2, -8(%ebp)                // put value 2 into stack, (int b)


/*push the paramters of sum function into statck*/
/*remember, C convention push the last parameter into stack first*/
    movl    -8(%ebp), %eax           // value of eax = content of ((value of ebp) - 8)
                                                   // integers are 4 bytes. This is "int b"
    movl    %eax, 4(%esp)            // content of ((value of esp)+4) = value of eax
    movl    -4(%ebp), %eax          // this is "int a" of sum() parameters
    movl    %eax, (%esp)             // even we assignment two paramaters on the
                                                  // stack, but we didn't change the value of esp
                                                  // "push", "pop", "call", ret" instructions change esp
/*start to call subprogram*/
    call    sum                             // push %eip;  movl sum, %eip
                                                 // this will save the return address of sum()




/*end this function*/
    movl    $1, %eax                   // put 1 into eax, this is the return value.
    leave                                     // movl %ebp, %esp; pop %ebp
                                                 // set the value of esp = the value of ebp, pop the 
                                                 // first element in stack, which is the saved ebp
    ret                                        // pop %eip, pop the return address, and save to eip


    .size    main, .-main
    .ident    "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"
    .section    .note.GNU-stack,"",@progbits










In active record, the sequence is:


..................4G......................


parameter n
parameter n-1
paremeter 1
Return address
previous ebp ______________current ebp point to here(betwen "perv ebp" & v1)
local variable1
local vraible2


.................. 0 .......................


esp suppose point to the top of stack. instrunction like push pop will change esp automatically. some other instruction like call, ret which include "push" or "pop" could also change esp.