asm error compiling huffyuv with VS2010 - visual-studio-2010

I'm trying to compile huffyuv with Visual Studio 2010. I get error message A2070 when assembling an asm file. I pasted the (some of) the relevant code below:
YUV_SHIFT MACRO mmb,mma,uyvy ; clobbers mm4,5
; mma:mmb = ABCDEFGHIJKLMNOP (VYUYVYUY...) - backwards from mem order
; we want mmb = EDGFIHKJ (prev pixel of same channel)
movq mm4,mmb
punpcklbw mmb,mma ; mm4:mmb = AIBJCKDLEMFNGOHP
punpckhbw mm4,mma
movq mm5,mmb
punpcklbw mmb,mm4 ; mm5:mmb = AEIMBFJNCGKODHLP
punpckhbw mm5,mm4
movq mm4,mmb
punpcklbw mmb,mm5 ; mm4:mmb = ACEGIKMOBDFHJLNP
punpckhbw mm4,mm5
psllq mmb,8+8*&uyvy ; mm4:mmb = EGIKMO__DFHJLNP_
psllq mm4,16-8*&uyvy
punpckhbw mmb,mm4 ; mmb = EDGFIHKJ (for YUY2; different for UYVY)
ENDM
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MEDIAN_PREDICT_PROC MACRO procname,uyvy
PUBLIC C _&procname
;void __cdecl mmx_MedianPredict(
; [esp+ 4] unsigned char* src,
; [esp+ 8] unsigned char* dst,
; [esp+12] unsigned char* src_end,
; [esp+16] int stride);
_&procname PROC
push ebp
mov ebp,esp
push edi
push esi
push ebx
; do the first row
mov esi,[ebp+4+4]
mov edi,[ebp+8+4]
mov ebx,[ebp+16+4]
lea ecx,[ebx+esi+8]
neg ebx
pxor mm2,mm2
movq mm3,[esi] ; for use in next loop
loop0:
movq mm0,[esi]
YUV_SHIFT mm2,mm0,uyvy
add esi,8
movq mm1,mm0
psubb mm1,mm2
movq [edi],mm1
movq mm2,mm0
add edi,8
cmp esi,ecx
jb loop0
mov ecx,[ebp+8+4] ; recopy first group of four, just for consistency with other compression methods
movd [ecx],mm3
; do the remaining rows
mov ecx,[ebp+12+4]
; mm2,3 are already initialized from previous loop
align 32
; pixel arrangement:
; mm3 mm1
; mm2 mm0
loop1:
; mm2,3 <- appropriate left and above-left pixels
movq mm0,[esi]
movq mm1,[esi+ebx]
YUV_SHIFT mm2,mm0,uyvy ; note: clobbers mm4,5
add esi,8
YUV_SHIFT mm3,mm1,uyvy
; mm4 <- median of mm1,mm2,(mm1+mm2-mm3)
movq mm4,mm2 ; (mm2,mm4) <- (min(mm1,mm2),max(mm1,mm2))
movq mm5,mm2 ; mm5 <- mm1+mm2-mm3
psubusb mm4,mm1
paddb mm5,mm1
psubb mm2,mm4
psubb mm5,mm3
paddb mm4,mm1
psubusb mm2,mm5 ; mm2 = max(mm2,mm5)
paddb mm2,mm5
movq mm5,mm4 ; mm4 = min(mm2,mm4)
psubusb mm5,mm2
psubb mm4,mm5 ; now mm4 = median
; write out the result and loop
movq mm2,mm0
movq mm3,mm1
psubb mm0,mm4
movq [edi],mm0
cmp esi,ecx
lea edi,[edi+8]
jb loop1
emms
pop ebx
pop esi
pop edi
pop ebp
retn
_&procname ENDP
ENDM
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MEDIAN_PREDICT_PROC mmx_MedianPredictYUY2,0 ; I get the error on this line
MEDIAN_PREDICT_PROC mmx_MedianPredictUYVY,1 ; and this as well
These are the first errors I get (I get more of the same kind later, but if I know how to fix the first ones, I can probably fix the rest).
1>C:\Development\huffyuv\huffyuv_a.asm(526): error A2070: invalid instruction operands
1> MEDIAN_PREDICT_PROC(41): Macro Called From
1> C:\Development\huffyuv\huffyuv_a.asm(526): Main Line Code
1>C:\Development\huffyuv\huffyuv_a.asm(527): error A2070: invalid instruction operands
1> MEDIAN_PREDICT_PROC(41): Macro Called From
1> C:\Development\huffyuv\huffyuv_a.asm(527): Main Line Code
I don't know very much about assembly code, so I'd be happy if someone could tell me where the problem is, and how to solve it.

Related

assembly code to scroll the screen one line down clearing the first line in the screen and then scrolls one line up if a key is pressed

I'm trying to scroll 1 line down then up but
a) I don't know how to test this code
b) I'm not sure which interrupt to use for "when a key is pressed"
I'd be much grateful for your help
Here's my code :
Data_segment_name segment para
firstline db 160 dup(0)
Data_segment_name ends
Stack_segment_name segment para stack
Stack_segment_name ends
Code_segment_name segment
Main_prog proc far
assume SS:Stack_segment_name,CS:Code_segment_name,DS:Data_segment_name
mov AX,Data_segment_name ; load the starting address of the data
mov DS,AX ; segment into DS reg.
;code scroll down (clear first line) then scroll back up(restore cleared line)
mov es,ax ;save first line
lea di,firstline
mov ax,0b800h
mov ds,ax
mov ax,0
mov si,ax
cld
mov cx,80
rep movsw ;save ends
;now let's scroll down :)
mov ax,0b800h
mov es,ax
mov ax,0
mov di,ax
mov ax,160
mov si,ax
cld
mov cx,24*80
rep movsw
;now let's scroll up :)
int 21h ;check
mov ax,160*24
mov si,ax
mov ax,160*25
mov di,ax
std
mov cx,24*80
rep movsw
;restore first line
mov AX,Data_segment_name ; load the starting address of the data
mov DS,AX ; segment into DS reg.
lea si,firstline
mov ax,0
mov di,ax
cld
mov cx,80
rep movsw
mov ax,4c00h ; exit program
int 21h
Main_prog endp
Code_segment_name ends
end Main_prog
Ad a):
The test tool is called "debugger". I recommend Turbo Debugger (google for it).
Ad b):
Ralf Brown's interrupt list and TechHelp are good references. At a glance: Int 10h is for video, Int 16h is for keyboard, Int 21h is for MS-DOS.
You should switch to the simplified segment directives .CODE, .DATA, .STACK and to procedural programming PROC, ENDP. When your project grows, it will help to keep track of it.
Example:
.MODEL small
.STACK 1000h
.DATA
firstline db 160 dup(0)
.CODE
save_firstline PROC
push ds
mov ax, ds
mov es, ax
lea di, firstline
mov ax, 0b800h
mov ds, ax
mov ax, 0
mov si, ax
mov cx, 80
rep movsw
pop ds
ret
save_firstline ENDP
restore_firstline PROC
lea si, firstline
mov ax, 0b800h
mov es, ax
mov ax, 0
mov di, ax
mov cx, 80
rep movsw
ret
restore_firstline ENDP
scroll_up PROC
call save_firstline
mov ah, 6 ; http://www.ctyme.com/intr/rb-0096.htm
mov al, 1 ; number of lines to scroll
mov bh, 0 ; attribute
mov ch, 0 ; row top
mov cl, 0 ; col left
mov dh, 25 ; row bottom
mov dl, 80 ; col right
int 10h
ret
scroll_up ENDP
scroll_down PROC
mov ah, 7 ; http://www.ctyme.com/intr/rb-0097.htm
mov al, 1 ; number of lines to scroll
mov bh, 0 ; attribute
mov ch, 0 ; row top
mov cl, 0 ; col left
mov dh, 25 ; row bottom
mov dl, 80 ; col right
int 10h
call restore_firstline
ret
scroll_down ENDP
main PROC
mov ax, #data
mov ds, ax
waitForKey: ; http://webpages.charter.net/danrollins/techhelp/0229.HTM
mov ah, 1
int 16h
jnz gotKey ; jmp if key is ready
jmp waitForKey ; loop back and check for a key
gotKey:
mov ah, 0 ; key is ready, get it
int 16h ; now process the key
cmp ah, 48h ; <UP>
jne #F
call scroll_up
jmp waitforKey
##:
cmp ah, 50h ; <DOWN>
jne #F
call scroll_down
jmp waitForKey
##:
cmp al, 1Bh ; <ESC>
jne waitForKey
mov ax, 4C00h
int 21h
main ENDP
END main

Insertion sort in assembler doesn't sort

I'm trying to sort a array of numbers by Insertion sort but it not sort the numbers correctly. I've tried everything but it does not sort them As it should.
I would be happy if you could help me figure out where the problem and on how I can fix it thanks !!
section .rodata
MSG: DB "welcome to sortMe, please sort me",10,0
S1: DB "%d",10,0 ; 10 = '\n' , 0 = '\0'
section .data
array DB 5,1,7,3,4,9,12,8,10,2,6,11 ; unsorted array
len DB 12
section .text
align 16
global main
extern printf
main:
push MSG ; print welcome message
call printf
add esp,4 ; clean the stack
call printArray ;print the unsorted array
push ebp ;save old frame pointer
mov ebp,esp ;create new frame on stack
pusha
mov esi,array
mov ecx,8
OuterLoop:
mov ebx,ecx
InnerLoop:
add esi,ebx ;basically makes array[0] to array[ebx]
mov eax,[esi] ;eax=array[ebx]
sub esi,8
mov edx,[esi] ; edx=array[ebx-1]
add esi,8
cmp eax,edx ; if(eax<edx)
jle skip2 ; skip the loop
;else:
mov [esi],edx ;array[ebx]=array[ebx-1]
sub esi,8
mov [esi],eax ; array[ebx-1]=array[ebx]
add esi,8
sub esi,ebx ; return the array to its original state (array[0])
sub ebx,8
cmp ebx,0
jne InnerLoop
skip1:
add ecx,8
cmp ecx,96
jle OuterLoop
popa ;restore registers
mov esp,ebp ;clean the stack frame
pop ebp
push MSG ; print welcome message (to divide between the unsorted and sorted)
call printf
add esp,4 ; clean the stack
call printArray
mov eax, 1 ;exit system call
int 0x80
printArray:
push ebp ;save old frame pointer
mov ebp,esp ;create new frame on stack
pusha ;save registers
mov eax,0
mov ebx,0
mov edi,0
mov esi,0 ;array index
mov bl,byte[len]
add edi,ebx ; edi = array size
print_loop:
cmp esi,edi
je print_end
mov al ,byte[array+esi] ;set num to print in eax
push eax
push S1
call printf
add esp,8 ;clean the stack
inc esi
jmp print_loop
print_end:
popa ;restore registers
mov esp,ebp ;clean the stack frame
pop ebp ;return to old stack frame
ret
skip2:
sub esi,ebx ; return the array to the original state
jmp skip1
You're horribly mixing 3 sizes!
1. Array of bytes
2. Values of dwords
3. Steps of qwords
Once you've decided what size to use beware of this code. In its current qword form it does an extra iteration! (use jl OuterLoop)
cmp ecx,96
jle OuterLoop
Why don't you use MOVZX to EAX in this line? It's much cleaner.
mov al ,byte[array+esi] ;set num to print in eax
The same applies to
mov bl,byte[len]
By putting mov esi,array right after OuterLoop: you can avoid that ugly detour via SKIP2.

I can't figure out how to delete a row in my tasm assembly homework

I have a compiled assembly program and I'm asked to modify it by removing the last row seen in the cmd prompt. I'm new at assembly so I can't find a solution.
When you run it 5 rows appear, and I'm trying to delete the row below;
Press [q]uit [e]xecute [c]lear:
;Serhad Ali Turhan 040060390
.8086
.MODEL small
.STACK 256
.DATA
;~~~~~~ Declarations ~~~~~~~~
CR equ 13d
LF equ 10d
cPrompt DB 'Press [q]uit [e]xecute [c]lear: $'
cName DB 'SERHAD ALI TURHAN',CR,LF,'$'
cNum DB 'Electronical Engineering',CR,LF,'$'
cSch DB 'ITU Ayazaga Kampusu 34469 Maslak-ISTANBUL',CR,LF,'$'
vDW DB 0 ;Day of the Week
vMon DB 0 ;Month
vDM DB 0 ;Day of the month
cDW0 DB 'SUNDAY$ ' ;All days are 10 bytes
cDW1 DB 'MONDAY$ '
cDW2 DB 'TUESDAY$ '
cDW3 DB 'WEDNESDAY$'
cDW4 DB 'THURSDAY$ '
cDW5 DB 'FRIDAY$ '
cDW6 DB 'SATURDAY$ '
vI2S_I DW 0 ;2 bytes
vI2S_S DB ?,?,?,?,'$' ;4 bytes
cExcode DB 0
;~~~~~~~~ Main Program ~~~~~~~~
.CODE
MAIN PROC
mov ax,#data ; Initialize DS to address
mov ds,ax ; of data segment
call pClr
jmp pExecute
jmp pMenu ;
;~~~~~ Menu ~~~~~
pMenu:
lea dx,cPrompt ;
call puts ;
call getc ;AL has user selection
push ax ;Store it
call pNL ;
pop ax ;
cmp al,'q' ;al?=q
je lQuit ;Quit
cmp al,'c' ;al?=c
je lClr ;Clear screen
cmp al,'e' ;
je pExecute ;
jmp pMenu ;
lClr:
call pClr
jmp pMenu ;
lQuit:
call pQuit
;~~~~~~~~
pExecute:
call pInfo
call pClock
call pDate
call pNL
jmp pMenu ;
pInfo:
lea dx,cName ;
call puts ;Display Name
lea dx,cNum
call puts ;Display Department
lea dx,cSch
call puts ;Display School Address
ret
pClock:
mov ah,2ch ;get time
int 21h
push dx
push cx
mov al,ch ;ch->hour
call pDisp
mov dl,':'
call putc
pop ax ;cl->minute
call pDisp
mov dl,':'
call putc
pop ax ;dh->seconds
mov al,ah
call pDisp
call pNL
ret
pDate:
mov ah,2ah ;get date
int 21h
mov vDW,al ;Store day of week
mov vMon,dh ;Store month
mov vDM,dl ;Store day of month
mov vI2S_I,cx ;Year will be stored in
call pI2S ;vI2S_s as ASCII
mov al,vDM ;Print day of month
call pDisp
mov dl,'.'
call putc
mov al,vMon ;Print month
call pDisp
mov dl,'.'
call putc
lea dx,vI2S_S ;Print year
call puts
mov dl,'-'
call putc
call pDW ;Print day of week
ret
pDW:
mov al,vDW
mov bl,10 ;All days are 10 bytes
mul bl
mov ah,0
mov bx,ax
lea dx,cDW0[bx]
call puts
ret
pDisp:
xor ah,0 ;
aam
add ax,3030h ;
push ax
mov dl,ah ;
call putc
pop dx
call putc
ret
;vI2S_I=1000*vI2S_S[0]+100*vI2S_S[1]+10*vI2S_S[2]+vI2S_S[3]
pI2S: ;intToStr
mov cx,1000 ;
mov ax,vI2S_I ;
mov dx,0
div cx ;
add al,'0'
mov vI2S_S,al ;
mov cx,100 ;
mov ax,dx
mov dx,0
div cx
add al,'0'
mov vI2S_s[1],al
mov cx,10 ;
mov ax,dx
mov dx,0
div cx
add al,'0'
mov vI2S_s[2],al
add dl,'0'
mov vI2S_s[3],dl ;
ret
;~~~~~~~~ Screen I/O Functions ~~~~~~~~
getc:
mov ah,1h ;read character from keyboard
int 21h ;to al
ret ;
putc:
mov ah,2h ;display character
int 21h ;at dl
ret ;
puts:
mov ah,9h ;display string terminated by '$'
int 21h ;at the adress dx
ret ;
;~~ Clear screen ~~~~
pClr:
mov ax,03h ;
int 10h ;
ret ;
;~~ New Line ~~~~~~~
pNL:
mov dl,CR ;
call putc ;
mov dl,LF ;
call putc ;
ret
;~~~~~~~~~ Exit ~~~~~~~~~~~~~~~
;return to DOS
pQuit:
mov ah,4Ch ; DOS function: Exit program
mov al,cExcode ; Return exit code value
int 21h ; Call DOS. Terminate program
MAIN ENDP
END MAIN ; End of program / entry point
I'll offer some guiding questions:
Does the text that you're looking to prevent appear in the code?
Is it identified in some way?
Does that identifier exist elsewhere in the code?
Where does that usage take you?
There are only a handfull of instructions that you care about. These questions will help you find them, and hopefully understand which one to delete.

why there are meaningless asm code in gcc "start" function (before main)?

I am a bit interested in what does the run time do, so I write a simple c program like below.(I do not paste the code of some_function. I think it's not important.)
int main(int argc, char *argv[]) {
some_fucntion();
return;
}
I use i686-apple-darwin10-llvm-gcc-4.2 on my Mac(10.6.8, Intel Core) and compiler the source with following command. Actually I have tried to use O3 and get same result.
gcc -O0 -o test test.c
Then I type following command and get those asm code.
otool -tV test
I get the following asm code. I guess those code relates to prepare the arguments for main function. But I still can't figure out why there are a loop to set eax to 0x00? And why there are a "jmp" instruction? so the next instruction will never be executed, right?
I would be really appreciate if anyone could explain the whole asm code here. Thanks.
start:
0000000100000d20 pushq $0x00
0000000100000d22 movq %rsp,%rbp
0000000100000d25 andq $0xf0,%rsp
0000000100000d29 movq 0x08(%rbp),%rdi
0000000100000d2d leaq 0x10(%rbp),%rsi
0000000100000d31 movl %edi,%edx
0000000100000d33 addl $0x01,%edx
0000000100000d36 shll $0x03,%edx
0000000100000d39 addq %rsi,%rdx
0000000100000d3c movq %rdx,%rcx
0000000100000d3f jmp 0x100000d45
0000000100000d41 addq $0x08,%rcx
0000000100000d45 cmpq $0x00,(%rcx)
0000000100000d49 jne 0x100000d41
0000000100000d4b addq $0x08,%rcx
0000000100000d4f callq _main
0000000100000d54 movl %eax,%edi
0000000100000d56 callq 0x100000e7c ; symbol stub for: _exit
0000000100000d5b hlt
0000000100000d5c nop
start:
0000000100000d20 pushq $0x00 ; push NULL (end of dynamic frame pointer chain)
0000000100000d22 movq %rsp,%rbp ; set frame pointer
0000000100000d25 andq $0xf0,%rsp ; align stack
0000000100000d29 movq 0x08(%rbp),%rdi ; mov argc to 1st arg
0000000100000d2d leaq 0x10(%rbp),%rsi ; mov argv to 2nd arg
0000000100000d31 movl %edi,%edx ; \
0000000100000d33 addl $0x01,%edx ; > 3rd arg = argv + (argc + 1) * 8
0000000100000d36 shll $0x03,%edx ; > = envp
0000000100000d39 addq %rsi,%rdx ; /
0000000100000d3c movq %rdx,%rcx ; \
0000000100000d3f jmp 0x100000d45 ; >
0000000100000d41 addq $0x08,%rcx ; > find 1st NULL after envp and
0000000100000d45 cmpq $0x00,(%rcx) ; > move to 4th arg
0000000100000d49 jne 0x100000d41 ; /
0000000100000d4b addq $0x08,%rcx ; and add 8 (apple)
0000000100000d4f callq _main ; call main
0000000100000d54 movl %eax,%edi ; move return value to 1st arg
0000000100000d56 callq 0x100000e7c ; and call _exit (doesn't return)
0000000100000d5b hlt
0000000100000d5c nop
apple is an Apple-specific argument that contains the path to the executable (source).

Help with Assembly. Segmentation fault when compiling samples on Mac OS X

I'm trying to learn assembly using Dr Paul Carter's pcasm book: http://www.drpaulcarter.com/pcasm/
The author doesn't packaged Mac OS X samples, then I've started using from linux sources. Here is the first sample, that uses his library asm_io.
I'm getting Segmentation Fault when running it. Why? What need to be changed to run in mac?
I think if you know asm, maybe you can tell me what's happening.
Here's the sources.
asm_io.asm:
;
; file: asm_io.asm
; Assembly I/O routines
; To assemble for DJGPP
; nasm -f coff -d COFF_TYPE asm_io.asm
; To assemble for Borland C++ 5.x
; nasm -f obj -d OBJ_TYPE asm_io.asm
; To assemble for Microsoft Visual Studio
; nasm -f win32 -d COFF_TYPE asm_io.asm
; To assemble for Linux
; nasm -f elf -d ELF_TYPE asm_io.asm
; To assemble for Watcom
; nasm -f obj -d OBJ_TYPE -d WATCOM asm_io.asm
; IMPORTANT NOTES FOR WATCOM
; The Watcom compiler's C library does not use the
; standard C calling convention. For example, the
; putchar() function gets its argument from the
; the value of EAX, not the stack.
%define NL 10
%define CF_MASK 00000001h
%define PF_MASK 00000004h
%define AF_MASK 00000010h
%define ZF_MASK 00000040h
%define SF_MASK 00000080h
%define DF_MASK 00000400h
%define OF_MASK 00000800h
;
; Linux C doesn't put underscores on labels
;
%ifdef ELF_TYPE
%define _scanf scanf
%define _printf printf
%define _getchar getchar
%define _putchar putchar
%endif
;
; Watcom puts underscores at end of label
;
%ifdef WATCOM
%define _scanf scanf_
%define _printf printf_
%define _getchar getchar_
%define _putchar putchar_
%endif
%ifdef OBJ_TYPE
segment .data public align=4 class=data use32
%else
segment .data
%endif
int_format db "%i", 0
string_format db "%s", 0
reg_format db "Register Dump # %d", NL
db "EAX = %.8X EBX = %.8X ECX = %.8X EDX = %.8X", NL
db "ESI = %.8X EDI = %.8X EBP = %.8X ESP = %.8X", NL
db "EIP = %.8X FLAGS = %.4X %s %s %s %s %s %s %s", NL
db 0
carry_flag db "CF", 0
zero_flag db "ZF", 0
sign_flag db "SF", 0
parity_flag db "PF", 0
overflow_flag db "OF", 0
dir_flag db "DF", 0
aux_carry_flag db "AF", 0
unset_flag db " ", 0
mem_format1 db "Memory Dump # %d Address = %.8X", NL, 0
mem_format2 db "%.8X ", 0
mem_format3 db "%.2X ", 0
stack_format db "Stack Dump # %d", NL
db "EBP = %.8X ESP = %.8X", NL, 0
stack_line_format db "%+4d %.8X %.8X", NL, 0
math_format1 db "Math Coprocessor Dump # %d Control Word = %.4X"
db " Status Word = %.4X", NL, 0
valid_st_format db "ST%d: %.10g", NL, 0
invalid_st_format db "ST%d: Invalid ST", NL, 0
empty_st_format db "ST%d: Empty", NL, 0
;
; code is put in the _TEXT segment
;
%ifdef OBJ_TYPE
segment text public align=1 class=code use32
%else
segment .text
%endif
global read_int, print_int, print_string, read_char
global print_char, print_nl, sub_dump_regs, sub_dump_mem
global sub_dump_math, sub_dump_stack
extern _scanf, _printf, _getchar, _putchar
read_int:
enter 4,0
pusha
pushf
lea eax, [ebp-4]
push eax
push dword int_format
call _scanf
pop ecx
pop ecx
popf
popa
mov eax, [ebp-4]
leave
ret
print_int:
enter 0,0
pusha
pushf
push eax
push dword int_format
call _printf
pop ecx
pop ecx
popf
popa
leave
ret
print_string:
enter 0,0
pusha
pushf
push eax
push dword string_format
call _printf
pop ecx
pop ecx
popf
popa
leave
ret
read_char:
enter 4,0
pusha
pushf
call _getchar
mov [ebp-4], eax
popf
popa
mov eax, [ebp-4]
leave
ret
print_char:
enter 0,0
pusha
pushf
%ifndef WATCOM
push eax
%endif
call _putchar
%ifndef WATCOM
pop ecx
%endif
popf
popa
leave
ret
print_nl:
enter 0,0
pusha
pushf
%ifdef WATCOM
mov eax, 10 ; WATCOM doesn't use the stack here
%else
push dword 10 ; 10 == ASCII code for \n
%endif
call _putchar
%ifndef WATCOM
pop ecx
%endif
popf
popa
leave
ret
sub_dump_regs:
enter 4,0
pusha
pushf
mov eax, [esp] ; read FLAGS back off stack
mov [ebp-4], eax ; save flags
;
; show which FLAGS are set
;
test eax, CF_MASK
jz cf_off
mov eax, carry_flag
jmp short push_cf
cf_off:
mov eax, unset_flag
push_cf:
push eax
test dword [ebp-4], PF_MASK
jz pf_off
mov eax, parity_flag
jmp short push_pf
pf_off:
mov eax, unset_flag
push_pf:
push eax
test dword [ebp-4], AF_MASK
jz af_off
mov eax, aux_carry_flag
jmp short push_af
af_off:
mov eax, unset_flag
push_af:
push eax
test dword [ebp-4], ZF_MASK
jz zf_off
mov eax, zero_flag
jmp short push_zf
zf_off:
mov eax, unset_flag
push_zf:
push eax
test dword [ebp-4], SF_MASK
jz sf_off
mov eax, sign_flag
jmp short push_sf
sf_off:
mov eax, unset_flag
push_sf:
push eax
test dword [ebp-4], DF_MASK
jz df_off
mov eax, dir_flag
jmp short push_df
df_off:
mov eax, unset_flag
push_df:
push eax
test dword [ebp-4], OF_MASK
jz of_off
mov eax, overflow_flag
jmp short push_of
of_off:
mov eax, unset_flag
push_of:
push eax
push dword [ebp-4] ; FLAGS
mov eax, [ebp+4]
sub eax, 10 ; EIP on stack is 10 bytes ahead of orig
push eax ; EIP
lea eax, [ebp+12]
push eax ; original ESP
push dword [ebp] ; original EBP
push edi
push esi
push edx
push ecx
push ebx
push dword [ebp-8] ; original EAX
push dword [ebp+8] ; # of dump
push dword reg_format
call _printf
add esp, 76
popf
popa
leave
ret 4
sub_dump_stack:
enter 0,0
pusha
pushf
lea eax, [ebp+20]
push eax ; original ESP
push dword [ebp] ; original EBP
push dword [ebp+8] ; # of dump
push dword stack_format
call _printf
add esp, 16
mov ebx, [ebp] ; ebx = original ebp
mov eax, [ebp+16] ; eax = # dwords above ebp
shl eax, 2 ; eax *= 4
add ebx, eax ; ebx = & highest dword in stack to display
mov edx, [ebp+16]
mov ecx, edx
add ecx, [ebp+12]
inc ecx ; ecx = # of dwords to display
stack_line_loop:
push edx
push ecx ; save ecx & edx
push dword [ebx] ; value on stack
push ebx ; address of value on stack
mov eax, edx
sal eax, 2 ; eax = 4*edx
push eax ; offset from ebp
push dword stack_line_format
call _printf
add esp, 16
pop ecx
pop edx
sub ebx, 4
dec edx
loop stack_line_loop
popf
popa
leave
ret 12
sub_dump_mem:
enter 0,0
pusha
pushf
push dword [ebp+12]
push dword [ebp+16]
push dword mem_format1
call _printf
add esp, 12
mov esi, [ebp+12] ; address
and esi, 0FFFFFFF0h ; move to start of paragraph
mov ecx, [ebp+8]
inc ecx
mem_outer_loop:
push ecx
push esi
push dword mem_format2
call _printf
add esp, 8
xor ebx, ebx
mem_hex_loop:
xor eax, eax
mov al, [esi + ebx]
push eax
push dword mem_format3
call _printf
add esp, 8
inc ebx
cmp ebx, 16
jl mem_hex_loop
mov eax, '"'
call print_char
xor ebx, ebx
mem_char_loop:
xor eax, eax
mov al, [esi+ebx]
cmp al, 32
jl non_printable
cmp al, 126
jg non_printable
jmp short mem_char_loop_continue
non_printable:
mov eax, '?'
mem_char_loop_continue:
call print_char
inc ebx
cmp ebx, 16
jl mem_char_loop
mov eax, '"'
call print_char
call print_nl
add esi, 16
pop ecx
loop mem_outer_loop
popf
popa
leave
ret 12
; function sub_dump_math
; prints out state of math coprocessor without modifying the coprocessor
; or regular processor state
; Parameters:
; dump number - dword at [ebp+8]
; Local variables:
; ebp-108 start of fsave buffer
; ebp-116 temp double
; Notes: This procedure uses the Pascal convention.
; fsave buffer structure:
; ebp-108 control word
; ebp-104 status word
; ebp-100 tag word
; ebp-80 ST0
; ebp-70 ST1
; ebp-60 ST2 ...
; ebp-10 ST7
;
sub_dump_math:
enter 116,0
pusha
pushf
fsave [ebp-108] ; save coprocessor state to memory
mov eax, [ebp-104] ; status word
and eax, 0FFFFh
push eax
mov eax, [ebp-108] ; control word
and eax, 0FFFFh
push eax
push dword [ebp+8]
push dword math_format1
call _printf
add esp, 16
;
; rotate tag word so that tags in same order as numbers are
; in the stack
;
mov cx, [ebp-104] ; ax = status word
shr cx, 11
and cx, 7 ; cl = physical state of number on stack top
mov bx, [ebp-100] ; bx = tag word
shl cl,1 ; cl *= 2
ror bx, cl ; move top of stack tag to lowest bits
mov edi, 0 ; edi = stack number of number
lea esi, [ebp-80] ; esi = address of ST0
mov ecx, 8 ; ecx = loop counter
tag_loop:
push ecx
mov ax, 3
and ax, bx ; ax = current tag
or ax, ax ; 00 -> valid number
je valid_st
cmp ax, 1 ; 01 -> zero
je zero_st
cmp ax, 2 ; 10 -> invalid number
je invalid_st
push edi ; 11 -> empty
push dword empty_st_format
call _printf
add esp, 8
jmp short cont_tag_loop
zero_st:
fldz
jmp short print_real
valid_st:
fld tword [esi]
print_real:
fstp qword [ebp-116]
push dword [ebp-112]
push dword [ebp-116]
push edi
push dword valid_st_format
call _printf
add esp, 16
jmp short cont_tag_loop
invalid_st:
push edi
push dword invalid_st_format
call _printf
add esp, 8
cont_tag_loop:
ror bx, 2 ; mov next tag into lowest bits
inc edi
add esi, 10 ; mov to next number on stack
pop ecx
loop tag_loop
frstor [ebp-108] ; restore coprocessor state
popf
popa
leave
ret 4
asm_io.inc:
extern read_int, print_int, print_string
extern read_char, print_char, print_nl
extern sub_dump_regs, sub_dump_mem, sub_dump_math, sub_dump_stack
%macro dump_regs 1
push dword %1
call sub_dump_regs
%endmacro
;
; usage: dump_mem label, start-address, # paragraphs
%macro dump_mem 3
push dword %1
push dword %2
push dword %3
call sub_dump_mem
%endmacro
%macro dump_math 1
push dword %1
call sub_dump_math
%endmacro
%macro dump_stack 3
push dword %3
push dword %2
push dword %1
call sub_dump_stack
%endmacro
first.asm
;
; file: first.asm
; First assembly program. This program asks for two integers as
; input and prints out their sum.
;
; To create executable:
; Using djgpp:
; nasm -f coff first.asm
; gcc -o first first.o driver.c asm_io.o
;
; Using Linux and gcc:
; nasm -f elf first.asm
; gcc -o first first.o driver.c asm_io.o
;
; Using Borland C/C++
; nasm -f obj first.asm
; bcc32 first.obj driver.c asm_io.obj
;
; Using MS C/C++
; nasm -f win32 first.asm
; cl first.obj driver.c asm_io.obj
;
; Using Open Watcom
; nasm -f obj first.asm
; wcl386 first.obj driver.c asm_io.obj
%include "asm_io.inc"
;
; initialized data is put in the .data segment
;
segment .data
;
; These labels refer to strings used for output
;
prompt1 db "Enter a number: ", 0 ; don't forget nul terminator
prompt2 db "Enter another number: ", 0
outmsg1 db "You entered ", 0
outmsg2 db " and ", 0
outmsg3 db ", the sum of these is ", 0
;
; uninitialized data is put in the .bss segment
;
segment .bss
;
; These labels refer to double words used to store the inputs
;
input1 resd 1
input2 resd 1
;
; code is put in the .text segment
;
segment .text
global _asm_main
_asm_main:
enter 0,0 ; setup routine
pusha
mov eax, prompt1 ; print out prompt
call print_string
call read_int ; read integer
mov [input1], eax ; store into input1
mov eax, prompt2 ; print out prompt
call print_string
call read_int ; read integer
mov [input2], eax ; store into input2
mov eax, [input1] ; eax = dword at input1
add eax, [input2] ; eax += dword at input2
mov ebx, eax ; ebx = eax
dump_regs 1 ; dump out register values
dump_mem 2, outmsg1, 1 ; dump out memory
;
; next print out result message as series of steps
;
mov eax, outmsg1
call print_string ; print out first message
mov eax, [input1]
call print_int ; print out input1
mov eax, outmsg2
call print_string ; print out second message
mov eax, [input2]
call print_int ; print out input2
mov eax, outmsg3
call print_string ; print out third message
mov eax, ebx
call print_int ; print out sum (ebx)
call print_nl ; print new-line
popa
mov eax, 0 ; return back to C
leave
ret
drive.c:
#include "cdecl.h"
int PRE_CDECL asm_main( void ) POST_CDECL;
int main()
{
int ret_status;
ret_status = asm_main();
return ret_status;
}
Now I compile it using:
nasm -f macho first.asm
nasm -f macho asm_io.asm
gcc first.o asm_io.o driver.c -o first -arch i386
Then run:
./first
Segmentation fault
It happens only when I'm using asm_io lib.
Thank you,
Daniel Koch
You seem to be using 32-bit assembly code here. One big difference among 32-bit Mac OS X and 32-bit Windows or Linux is that Mac requires the stack to be 16-byte aligned whenever you CALL a function. In other words, at the point in your code where you have a CALL instruction, it is required that ESP = #######0h.
The following may be interesting reads:
http://blogs.embarcadero.com/eboling/2009/05/20/5607
www.agner.org/optimize/calling_conventions.pdf

Resources