Hey again guys, I have been working on my exercises and I'm trying to convert a program from 16 bit to 32 bit. I tried running the original program and it didn't work for some odd reason or another so I've already flipped the registers and such to 32 bit but it still doesn't run correctly.
I think the answer here is fairly simple, it is just alluding my noobish mind.
Errors:
Error 1 error A2111: conflicting parameter definition C:\Irvine\Examples\Project_sample\Problem 20.asm 52 1 ASM_Project
Error 2 error A2004: symbol type conflict C:\Irvine\Examples\Project_sample\Problem 20.asm 10 1 ASM_Project
Code:
INCLUDE Irvine32.inc
;The purpose of this program is to parse a string, locate the offending segment "xxxx" and remove it from the string.
.data
target BYTE "abcxxxxdefghijklmop",0
start_add DWORD 3
no_chars DWORD 4
.code
main:
mov eax,@data
mov ds,eax
mov es,eax
mov edi,OFFSET target
push edi
mov eax,start_add
push eax
mov eax,no_chars
push eax
call str_remove
mov byte ptr[edi],'$'
mov ah,09h
mov edx,OFFSET target
int 21h
mov ah,4ch
int 21h
;----------------------------------------
str_remove PROC
;----------------------------------------
push ebp
mov ebp,esp
cld
mov ecx,[ebp+6]
call str_length
mov ecx,eax
sub ecx,[ebp+6]
sub ecx,[ebp+8]
mov edi,[ebp+10]
add edi,[ebp+8]
mov esi,edi
add esi,[ebp+6]
rep movsb
pop ebp
ret 8
str_remove ENDP
;----------------------------------------
str_length PROC
;input edi offset of the string
;output:ad
;----------------------------------------
push edi
mov eax,0
L1: cmp BYTE ptr [edi],0
je L2
inc edi
inc eax
jmp L1
L2:
pop edi
ret
str_length ENDP
END main
the first problem is
mov eax,@data
mov ds,eax
mov es,eax
32-bit windows uses a "flat" memory model
i.e., one big segment for everything
just remove those lines of code
the next problem is
mov byte ptr[edi],'$'
mov ah,09h
mov edx,OFFSET target
int 21h
mov ah,4ch
int 21h
use the WriteString function that is defined in Irvine32 to display strings
and, the "exit" macro or ExitProcess to terminate the program
INT's are essentially unusable in 32-bit apps
finally, the one that is spitting out errors, seems to be the use of "main"
maybe Irvine uses that symbol elsewhere
just change it to something a little different
there are a couple issues, here
str_remove PROC
;----------------------------------------
push ebp
mov ebp,esp
cld
mov ecx,[ebp+6]
call str_length
mov ecx,eax
sub ecx,[ebp+6]
sub ecx,[ebp+8]
mov edi,[ebp+10]
add edi,[ebp+8]
mov esi,edi
add esi,[ebp+6]
rep movsb
pop ebp
ret 8
str_remove ENDP
[EBP+6] [EBP+10] ????
check your math on those :biggrin:
the assembler will take care of the stack frame for you, if you use it to fullest extent
MyFunc PROC Argument1:DWORD,Argument2:DWORD
mov edi,Argument1
mov ecx,Argument2
;
; more code
;
ret
MyFunc ENDP
if you provide a PROTOtype near the beginning of source (usually right after the INCLUDE's)
MyFunc PROTO :DWORD,:DWORD
you can call the function with the arguments by using INVOKE
INVOKE MyFunc,Arg1,Arg2
the assembler generates a prologue at the beginning of the routine to set up the stack frame
and, anywhere a RET is encountered, it will generate an epilogue to clean it up
also, it will clean up the arguments from the stack (because we are using StdCall)
so - in my example, it will use RET 8 because there are 2 dword parms to remove
one final note....
Kip does not follow the intel ABI, MS does :P
EAX, ECX, EDX are volatile across function calls
EAX is often used to return a result or status
EBX, ESI, EDI, EBP are preserved across function calls
the direction flag should be cleared when calling an API function
so - you can assume it is cleared, unless you have set it
and - if you set it, you should clear it when done
these rules apply to windows function calls
but, we generally try to follow the same set of rules when we write functions
when Kip and Randy wrote their 32-bit books, they more-or-less "upgraded" their old 16-bit routines
so - they still pass values in registers and, in some cases, do not follow the ABI
it would be nice if they would update their books and libraries :t
So the guy who wrote the code had no idea what he was doing. Yeah, I figured as much. It looked all wrong to me when I was looking at it. For the last few weeks they have had instructional videos on the website that kinda give you a starting point, but this week (finals week) they are just like "Oh...figure it out for yourselves"
Alas, examples found on google search are less than accurate sometimes >.>
Quote from: Syre Lancaster on October 05, 2013, 03:58:21 AM
So the guy who wrote the code had no idea what he was doing.
i hope you aren't refering to Kip - lol
we like Kip and Randy - they are actually good authors that have helped many get started
they just need to move away from the old 16-bit ways, is all
as for examples....
if you install the masm32 package
http://masm32.com/ (http://masm32.com/)
you will find tutorials, help files, and many examples
also - most of us use that set of libraries - so you are likely to get more help in the forum
use the book to understand individual instructions
use the masm32 libraries and examples to help write code :t
No, the example I was referring to was found online, unaffiliated with Kip Irvine. Thanks for that resource I may be able to get somewhere with this now ^.^
one more note - again
for every function in the Irvine32 library, there is probably an analogous function in the masm32 library
Irvine32: WriteString
you pass it arguments in registers, and it displays a string
Masm32: StdOut
you use INVOKE, passing the address of the null-terminated string on the stack, and it displays a string
there is also a "print" macro that can simplify some of your code
Irvine32: StrLength
you pass it arguments in registers, and it returns the length
Masm32: StrLen
you use INVOKE, passing the address of the null-terminated string on the stack, and it returns the length
there is also a "len" macro - lol
although, you don't have to use this function as often because StdOut gets the length for you :biggrin:
Quote from: dedndave on October 05, 2013, 03:45:47 AMwhen Kip and Randy wrote their 32-bit books, they more-or-less "upgraded" their old 16-bit routines
Indeed. You can "upgrade" 16-bit code, but often it makes more sense to ask "what should the code do?", and then re-write it from scratch. 32-bit code is a lot more powerful, because you have over 10,000 Windows API functions, plus the Masm32 library. \Masm32\help\hlhelp.chm is a good read in this respect - see e.g. Macro Categories/String macros/Find$ for your xxxx problem.
Quote from: Syre Lancaster on October 05, 2013, 03:58:21 AM
So the guy who wrote the code had no idea what he was doing.
The code most likely was assumed to run with the help of a DOS extender, in a 32-bit segmented memory model.
In this case the "guy" knew exactly what he was doing, but perhaps just forgot to mention how the sample was supposed to be assembled and linked - or you just missed this information bit.
> Kip does not follow the intel ABI, MS does
The Win32 ABI is a M$ invention - so M$ just followed their own ABI.
> The Win32 ABI is a M$ invention - so M$ just followed their own ABI.
Intel would disagree with you.
intel does define some ABI's - i know that much - lol
but - does it really matter to the beginner in this sub-forum ?
no - the point is - the ABI is followed by MS, and much of our code
it's not exactly followed by Kip and Randy, with regard to their libraries and examples
something they do that is really old-school is to pass arguments in register,
while the rest of us pass arguments on the stack
i know about fast call, so don't go there - again, not a beginner subject
for a beginner, it's confusing to see one thing in the book, and something entirely different elsewhere
worse, many university professors know less than the students - lol
they select a book (likely from an approved list) and tell the students to buy it
many of these professors are math teachers or come from some other discipline - lol
in the best cases, they are C programmers, themselves
it's rare to find one that is actually fluent in assembler
they don't understand the difference between 16-bit, 32-bit extensions, and win32
assembly language (for a beginner) is hard enough without all the waxing and waning
Ok, I take my "statement" back - before it causes major turbulence :icon_mrgreen:. It was anyway just a "by-the-way"-remark.
i'm not sure about the win32 ABI
but, intel has an "x32" ABI definition - not the same thing, though
Debunking x32 myths (https://blog.flameeyes.eu/2012/06/debunking-x32-myths) - very biased imo, the idea as such is a good one, and most benchmarks do give an advantage over x64.
deleted
The ABI is the mechanics of doing an API call, in Windows it filters down to an INT, same for Linux, same for DOS.
Quote from: japhethThe Win32 ABI is a M$ invention - so M$ just followed their own ABI.
In this instance japheth is correct. The OS defines the ABI.
ps, do we really need the M$ crap? It gets tiresome...
deleted
Quote from: sinsi on October 05, 2013, 09:11:10 PM
The ABI is the mechanics of doing an API call, in Windows it filters down to an INT, same for Linux, same for DOS.
I'm intrigued, I know that in 16 bit DOS apps we have BIOS and DOS INTs and in Linux INT 80h is used,
but how does this apply to Win32?
To make a ring3 to ring0 call you would use an interrupt gate, the NT calls boil down to loading the registers and an INT (2D maybe?).
for the most part, however, we call windows functions by pushing values on the stack and using CALL
the assembler has an internal macro named INVOKE to do this
INVOKE WriteFile,hFile,offset buffer,nNumberOfBytes,offset NumberOfBytesWritten,NULL
this is how WriteFile is defined for C
BOOL WINAPI WriteFile(
_In_ HANDLE hFile,
_In_ LPCVOID lpBuffer,
_In_ DWORD nNumberOfBytesToWrite,
_Out_opt_ LPDWORD lpNumberOfBytesWritten,
_Inout_opt_ LPOVERLAPPED lpOverlapped
);
http://msdn.microsoft.com/en-us/library/windows/desktop/aa365747%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/aa365747%28v=vs.85%29.aspx)
there are some 10 to 100 thousand such functions
not as easy to memorize as the DOS interrupts, but much more powerful :P
@sinsi
OK INT3h is used for debugging and INT 2dh mostly for drivers?
Are there others that are used for a "normal" user mode app running at Ring3
or as dedndave writes we simply push onto the stack and call the required API?
I have used INT3h many times and am comfortable with the Windows API, but never heard of other INTs
hence the reason for asking.
the win32 ABI becomes more evident when you start writing GUI applications
the OS sends messages to your window by calling a WndProc function that is defined by you
you must obey the rules of the ABI when handling these messages
so - if you want to call a function from WndProc, that function should obey the rules
OK but how does the ABI relate to INTs and which ones?
That is the part I don't understand.
Are you saying that Windows messages are INT based?
well - in 16-bit DOS - there was a different ABI - not sure it was ever called that
you passed values in registers and, in some cases, certain registers were preserved
then, you call the function with INT
the use of INT may be internal to some win32 functions
truthfully, i don't know how much INT's are used by the OS
probably used more for "housekeeping" operations than anything
for win32, you can more-or-less forget about INT's
you will use INT 3 for debugging
but, unless you are writing drivers, that's about all you'll see of them
Still not clear on how INTs relate to Win32.
In DOS we do like so:
MOV AH,9
INT 21H
RET
and in Linux (32 bit CLI app):
section .text
global _start ;must be declared for linker (ld)
_start: ;tell linker entry point
mov edx,len ;message length
mov ecx,msg ;message to write
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
msg db 'Hello, world!',0xa ;our string
len equ $ - msg ;length of our string
But in Win32, I have only ever seen the use of the API, pushing onto the stack and calling.
Eventually you need to get to ring0, this is the true windows kernel e.g. your exe calls a function in kernel32.dll which calls a function in ntdll.dll which calls a function in...until you get to the lowest user level. then it's load the regs and perform an int.
Ring3 to ring0 is expensive as far as cycles go so a lot of user-type information is cached, it stays in userland.
@dedndave
OK got it, you updated your previous post after I wrote mine.
@sinsi
I understand that certain functions require Ring0, which normally use NTDLL but other then that?
...
sorry about that, Paulo
i am an old fart - seems like everything is an afterthought - lol
Quote from: dedndave on October 06, 2013, 12:52:23 AM
sorry about that, Paulo
i am an old fart - seems like everything is an afterthought - lol
:t I know the feeling well. :biggrin:
@vertograd
I think software INTs under Win32 are emulated in NTVM when one runs 16 Bit code? is that correct?
...
that's correct
you are running in protected mode
and - INT's are allowed in ring 0
NTVDM emulates them so that most old 16-bit code can work in a protected environment
(New Technology Virtual Dos Machine)
Quote from: dedndave on October 06, 2013, 03:49:21 AM
NTVDM emulates them so that most old 16-bit code can work in a protected environment
And the same for 32-bit DOS apps.
Quote from: Paulo on October 06, 2013, 01:04:04 AM
I think software INTs under Win32 are emulated in NTVM when one runs 16 Bit code? is that correct?
Not necessarily. It's always true for 80386 and 80486 cpus, but beginning with the Pentium, there exists a flag in CR4, called VME. In short, this flag, in conjunction with a bit-table in the current TSS, allows to avoid leaving V86-mode if a software INT is executed.
See for example http://www.rcollins.org/articles/vme1/VME_Overview.html (http://www.rcollins.org/articles/vme1/VME_Overview.html).
Hardware interrupts and exceptions are not affected by VME, and since the OS does also not allow I/O-port access in ring 3, there is no security problem.
WOW.
(http://s22.postimg.org/5k3y0oy69/vme.jpg)