Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

input & output in assembly

255 views
Skip to first unread message

Dpak Cherian

unread,
Jan 23, 2004, 7:33:38 PM1/23/04
to
in 16-bit assembly is there any way to accept numbers as input and display them.
btw, is there anything like cin & cout in assembly

PS. I'm a complete newbie so plz excuse

Brandon J. Van Every

unread,
Jan 23, 2004, 11:00:09 PM1/23/04
to
Dpak Cherian wrote:
> in 16-bit assembly

I'm slightly curious why you care about 16-bit ASM in the modern day.
Actually, I'm not curious, that's the wrong word. I'm saying you shouldn't
be bothering with 16-bit ASM for any reason. 32-bit is minimum. The only
16-bit systems of interest are "retro" HW platforms for old games and the
like, and there's no reason you should learn those at a first go.

> is there any way to accept numbers as input and
> display them. btw, is there anything like cin & cout in assembly
>
> PS. I'm a complete newbie so plz excuse

Assembly is the lowest level of coding you can do for a computer, short of
giving it 1's and 0's directly. Assembly is generally used to build an
Operating System from scratch. In fact, not even that, just parts of an
operating system. Most parts of an OS are built in a slightly higher level
language like C. cin, cout, cerr, and "displaying" numbers are all
exceedingly high level capabilities compared to ASM code. ASM code just
allows you to push values into and out of a CPU, and other extremely basic
OS tasks.

In other words, no. Not in ASM itself.

If your *development tool* has a way of displaying numbers as an ASM program
executes, that's a different matter entirely. But that has nothing to do
with ASM itself, that is a capability of the tool. No tool, no numbers.

The way ASM + CPU turns into an actual OS and computer that can do I/O, is
you have specialized pieces of hardware that do various things when you read
/ write values to specific memory addresses. This is entirely CPU,
controller chipset, and OS specific. Generally speaking such techniques are
called "memory mapped I/O."

--
Cheers, www.indiegamedesign.com
Brandon Van Every Seattle, WA

20% of the world is real.
80% is gobbledygook we make up inside our own heads.


August Derleth

unread,
Jan 23, 2004, 11:00:46 PM1/23/04
to
Dpak Cherian wrote:

> in 16-bit assembly is there any way to accept numbers as input and display them.
> btw, is there anything like cin & cout in assembly

Not really. You need to rely on the services of a specific OS to do
anything like that, and what the OS gives you will not be as simple as
what C++ has.

You can look up various references about doing things like this once
you've decided which OS you will use. If you are using 16-bit Intel
chips (the 8088/8086 up to the 80286), the OS will probably be some
variant of DOS (MS-DOS, PC-DOS, DR-DOS, FreeDOS, etc.).

I have a question for you: Why do you want to use 16-bit chips? 32-bit
chips are more common now, certainly cheaper (all 16-bit Intel chips are
now antiques), and they do not impose as many restrictions on you. Plus,
with 32-bit chips you can use much better OSes (Linux, OpenBSD, Minix,
etc.).

>
> PS. I'm a complete newbie so plz excuse
>

Nobody will hold that against you here, as long as you make some effort
to do things for yourself.

--
My address is yvoregnevna gjragl-guerr gjb-gubhfnaq guerr ng lnubb qbg pbz
Note: Rot13 and convert spelled-out numbers to numerical equivalents.

Bx.C

unread,
Jan 23, 2004, 11:00:47 PM1/23/04
to

"Dpak Cherian" <dpakc...@fastmail.fm> wrote in message
news:476dbfa6.04012...@posting.google.com...

it's all done manually.. you have to know where you want the input to come
from... what data format it is in (ASCII numbers? packed BCD numbers? signed
32-bit integer? 80-bit floating point? etc.).... and after processing it..
you have to know where you want to place it..

if you could be so kind as to give a more specific (yet very basic)
question, i'll gladly supply an example answer....


Randall Hyde

unread,
Jan 24, 2004, 1:03:28 AM1/24/04
to
I agree with others who claim you should steer clear of 16-bit DOS
code these days. But if you insist, take a look at the "UCR Standard
Library for 80x86 Assembly Language Programmers" It has the routines
you're looking for, and many more. You can find the UCR stdlib at
http://webster.cs.ucr.edu.
While you're there, you might want to look at HLA (the high level
assembler) and "The Art of Assembly Language Programming"
Cheers,
Randy Hyde

"Dpak Cherian" <dpakc...@fastmail.fm> wrote in message
news:476dbfa6.04012...@posting.google.com...

John H. Guillory

unread,
Jan 24, 2004, 1:42:43 AM1/24/04
to
On Sat, 24 Jan 2004 00:33:38 +0000 (UTC), dpakc...@fastmail.fm
(Dpak Cherian) wrote:

>in 16-bit assembly is there any way to accept numbers as input and display them.
>btw, is there anything like cin & cout in assembly

No way, there's no way of doing cin/cout in assembly. Once the
compiler generates machine instructions, there is no cin/cout.
Actually, in reality there's only one GIGANTIC factor we must know
here.... What OS????? Seeing as how you did cross-post this to
comp.lang.asm.x86, I can rule out any non-intel 16-bit processors,
hybrid 8/16-bit processors and such.... Considering that all forms of
UNIX and LINUX are 32-bit or 64-bit, I can rule out Linux as the OS,
and can rule out Windows/XP, Windows/NT.... Now I *think* I can make
it fairly safe to assume your either using GEOS Ensamble, Windows
3.1/3.0 (maybe 2.0 or 1.0), or a version of MS-DOS/compatible OS.
With that in mind, that narrows down the scope of your answer a bit.
GEOS on the PC I only know GeoBASIC, and I don't think they sell it
any more, so I'll just say you have to find some other fool to help
you there if that's what you want.... Windows 3.0/3.1 your really up a
creak without a paddle. What the compilers do when you have cin/cout
in windows is usually create a window and write out text to that
window. Doing so will mean creating a window, keeping track of the
cursor position, creating a new font, writing the text out, updating
the cursor position, etc... Don't ask me to explain/write that....
Besides there's much more qualified people for that.... Now to the OS
I'm most qualified as a God at.... MS-DOS Compatible... (Which I'm
hoping you meant anyway....)

All MS-DOS functions are handled through INT 21h. Grab a copy of
Ralph Brown's interrupt primer. In it, you'll see Function 9.

Eg.


CODE SEGMENT PUBLIC 'Me'
ASSUME CS:CODE,DS:CODE,SS:None
Start: MOV AX, CS
MOV DS, AX ; DS=CS
MOV AH, 9 ; DOS Print String
MOV DX, OFFSET Data1 ; Our String
INT 21h
RET

Data1: DB 'This is our string.',13,10,'$'
CODE ENDS
END Start

The string *MUST* be terminated with a $.

For Standard Input, use AH=0Ah, DS:DX points to your buffer, which is
as follows:

1st Byte is the Maximum # bytes your buffer holds
2nd Byte is the # bytes actually read (on return)
3rd Byte onward is the actual string the user typed in.... Including
carridge return

CIN/COUT refers to Console In/Out, which in some C compilers means
direct screen writes. For that, you get to do things the hard way....
You move the string to the screen where you want it and handle the
attribute yourself.... Some C compilers will use INT 10h and use the
character out, others will just use STDOUT.... Either way, I highly
recommend you pick up Ralph Brown's interrupt primer and read the
introduction carefully, perhaps grab A86 and read up on how the INT
instruction works and 16-bit memory is layed out... Everyone hates it
when I recommend A86 manual, but it really does have some great
information in it. The older Art of Assembly language I believe is
geared towards 16-bit DOS assembly, and has some libraries that
provide easier access to input/output routines, though grasping an
understanding of what the library is doing really helps....

>PS. I'm a complete newbie so plz excuse

Not knowing, but having a desire to learn is not a problem.... Wanting
us to do something for you is a problem. And ASSUMING (as an
instructor once said) makes an ASS out of U and ME.... So just try not
to ASSUME that we know you are referring to MS-DOS or Intel, or
Windows 16-bit assembly.... And if you meant 16-bit motorola and you
cross-posted it to comp.lang.asm.x86 because you where too lazy to
check your posting before you sent it.... All I can say is you earned
any flames you get ;-)

Herbert Kleebauer

unread,
Jan 24, 2004, 4:00:59 AM1/24/04
to
"Brandon J. Van Every" wrote:

> I'm slightly curious why you care about 16-bit ASM in the modern day.
> Actually, I'm not curious, that's the wrong word. I'm saying you shouldn't
> be bothering with 16-bit ASM for any reason. 32-bit is minimum.

There are still much more 4/8 bit processors sold than 16/32/64 processors.
But even if an Intel 32 bit processor is used, a beginner always
should start learning assembly programming in real or V86 mode and
not in protected mode. The language of the processor is the same
but the interface to the operating system (int 21 or even BIOS) is
much simpler than the Win32 interface. And you can use almost all
32 bit instructions and addressing modes also in real/V86 mode.
The only restriction is the limit of 64k memory (without using
segmentation) which surely isn't a limitation for learning
assembly programming.

As an example a simple program which reads from stdin and writes
to stdout, converting all upper case characters to lower case.
To make it compatible with the win32 version, it uses mostly
32 bit instructions. But even then the generated executable
file size is only 109 bytes.

@=$100
loop: bsr.l getc ; get char from stdin
cmp.l #-1,r0 ; EOF
bne.b _10 ; branch if not
moveq.l #0,-(sp)
bsr.l ExitProcess ; exit program
_10: cmp.b #'A',r0
blo.b _20
cmp.b #'Z',r0
bhi.b _20
add.b #'a'-'A',r0
_20: bsr.l putc ; write char to stdout
br.b loop ; go on


putc: movem.l r0-r7,-(sp)
move.b r0,_buf
move.b #$40,m0
move.w #_buf,r1
move.w #1,r2
move.w #1,r3
trap #$21
movem.l (sp)+,r0-r7
rts.l
_buf: dc.b 0


getc: movem.l r0-r7,-(sp)
move.b #$3f,m0
move.w #_buf,r1
move.w #1,r2
eor.w r3,r3
trap #$21
bcs.b _10
cmp.w r0,r2
bne.b _10
movem.l (sp)+,r0-r7
move.b _buf,r0
rts.l
_10: movem.l (sp)+,r0-r7
move.l #-1,r0
rts.l
_buf: dc.b 0


ExitProcess:
move.b #$4c,m0
trap #$21


Now look at the same program in a win32 version. The main part
is identical to the above version, but the overhead is
terrible (especially for a beginner) and the generated exe
is 1024 bytes.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; STDINOUT.mac: copy stdin to stdout and convert all upper case ;;
;; letter to lower case ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

UseIdatSection=0 ; 0 if no idat section is used
UseUdatSection=0 ; 0 if no udat section is used

;#==================================================================#
;# Start of Headers #
;#==================================================================#

; +--------------------------------------------+
; | Start of DOS Header |
; +--------------------------------------------+

; DOS .EXE header
dc.b 'MZ' ; Magic number
dc.w dosfilesize\512 ; Bytes on last page of file (0->512)
dc.w (dosfilesize-1)/512+1
; Pages in file (Page=512 byte)
dc.w 0 ; Relocations (nr of entries)
dc.w doshead_end/16 ; Size of header size in paragraphs (16 byte)
dc.w 0 ; Minimum extra paragraphs needed
dc.w $ffff ; Maximum extra paragraphs needed
dc.w 0 ; Initial (relative) SS value (ss=load_adr+nr)
dc.w dosstack ; Initial SP value
dc.w 0 ; Checksum
dc.w dosmain ; Initial IP value
dc.w 0 ; Initial (relative) CS value (cs=load_adr+nr)
dc.w reloc ; File address of relocation table
dc.w 0 ; Overlay number
dc.w 0,0,0,0 ; Reserved words
dc.w 0 ; OEM identifier (for e_oeminfo)
dc.w 0 ; OEM information; e_oemid specific
dc.l 0,0,0,0,0 ; Reserved words
dc.l WinHeader ; File address of new exe header
reloc:
doshead_end:

@=$0
dosmain:move.w s6,-(sp)
move.w (sp)+,s0
move.w #_text,r1
move.b #$09,m0
trap #$21
move.w #$4c01,r0
trap #$21
_text: dc.b 'Nice to meet somebody who is still using DOS,',13,10
dc.b 'but his program requires Win32.',13,10,'$'
even 16

dosstack=@+256 ; 256 Byte stack
dosfilesize=@+256

; +--------------------------------------------+
; | End of DOS Header |
; +--------------------------------------------+


; +--------------------------------------------+
; | Start of Windows Header |
; +--------------------------------------------+

ImageBase== $00400000
SectionAlignment== 4096
FileAlignment== 512

WinHeader=@@
@=ImageBase

; see WINNT.H for information
dc.b 'PE',0,0 ; magic word
; _IMAGE_FILE_HEADER:
dc.w $014c ; Machine ($014c=Intel x86 processor)
dc.w NumberOfSections ; NumberOfSections
dc.l $36a57950 ; TimeDateStamp (seconds since 31.12.69 16:00)
dc.l 0 ; PointerToSymbolTable
dc.l 0 ; NumberOfSymbols
dc.w SizeOfOptionalHeader ; SizeOfOptionalHeader
dc.w $010f ; Charcteristics

; 0x0001 Relocation info stripped from file.
; 0x0002 File is executable (i.e. no unresolved externel references).
; 0x0004 Line nunbers stripped from file.
; 0x0008 Local symbols stripped from file.
; 0x0010 Agressively trim working set
; 0x0080 Bytes of machine word are reversed.
; 0x0100 32 bit word machine.
; 0x0200 Debugging info stripped from file in .DBG file
; 0x0400 If Image is on removable media, copy and run from the swap file.
; 0x0800 If Image is on Net, copy and run from the swap file.
; 0x1000 System File.
; 0x2000 File is a DLL.
; 0x4000 File should only be run on a UP machine
; 0x8000 Bytes of machine word are reversed.

@a=@ ; _IMAGE_OPTIONAL_HEADER
dc.w $010b ; Magic
dc.b 5 ; MajorLinkerVersion
dc.b 12 ; MinorLinkerVersion
dc.l SizeOfCode ; SizeOfCode
dc.l SizeOfInitializedData ; SizeOfInitializedData
dc.l SizeOfUninitializedData ; SizeOfUninitializedData
dc.l winmain-ImageBase ; AddressOfEntryPoint
dc.l BaseOfCode ; BaseOfCode
dc.l BaseOfData ; BaseOfData
dc.l ImageBase ; ImageBase
dc.l SectionAlignment ; SectionAlignment
dc.l FileAlignment ; FileAlignment
dc.w 4 ; MajorOperatingSystemVersion
dc.w 0 ; MinorOperatingSystemVersion
dc.w 0 ; MajorImageVersion
dc.w 0 ; MinorImageVersion
dc.w 4 ; MajorSubsystemVersion
dc.w 0 ; MinorSubsystemVersion
dc.l 0 ; Win32VersionValue
dc.l SizeOfImage ; SizeOfImage
dc.l SizeOfHeaders ; SizeOfHeaders
dc.l 0 ; CheckSum
dc.w 3 ; Subsystem
; 0: Unknown subsystem.
; 1: Image doesn't require a subsystem.
; 2: Image runs in the Windows GUI subsystem.
; 3: Image runs in the Windows character subsystem.
; 5: image runs in the OS/2 character subsystem.
; 7: image run in the Posix character subsystem.
; 8: image run in the 8 subsystem.
dc.w $0000 ; DllCharacteristics
dc.l $00100000 ; SizeOfStackReserve
dc.l $00001000 ; SizeOfStackCommit
dc.l $00100000 ; SizeOfHeapReserve
dc.l $00001000 ; SizeOfHeapCommit
dc.l $00000000 ; LoaderFlags
dc.l NumberOfRvaAndSize ; NumberOfRvaAndSize (entries
; in the data dir)

; ..............................................
; : Start of Image Data Directory :
; ..............................................

; virtual address, size
@b=@
dc.l 0,0 ; Export Directory
dc.l imp_start,imp_size ; Import Directory
dc.l 0,0 ; Resource Directory
dc.l 0,0 ; Exception Directory
dc.l 0,0 ; Security Directory
dc.l 0,0 ; Base Relocation Table
dc.l 0,0 ; Debug Directory
dc.l 0,0 ; Description String
dc.l 0,0 ; Machine Value (MIPS GP)
dc.l 0,0 ; TLS Directory
dc.l 0,0 ; Load Configuration Directory
dc.l 0,0 ; Bound Import Directory in headers
dc.l iat_start,iat_size ; Import Address Table
dc.l 0,0 ; 14
dc.l 0,0 ; 15
dc.l 0,0 ; 16

NumberOfRvaAndSize = (@-@b)/8
SizeOfOptionalHeader = @-@a

; ..............................................
; : End of Image Data Directory :
; ..............................................

; ..............................................
; : Start of Image Sections Header :
; ..............................................

@a=@

dc.b '.text',0,0,0 ; name
dc.l VSizeOf_text ; virtual size
dc.l VBaseOf_text ; virtual address
dc.l FSizeOf_text ; size of raw data
dc.l FBaseOf_text ; pointer to raw data
dc.l 0 ; pointer to relocatins
dc.l 0 ; pointer to line numbers
dc.w 0 ; number of relocations
dc.w 0 ; number of line numbers
dc.l $e0000020 ; characteristics


IF UseIdatSection
dc.b '.idat',0,0,0 ; name
dc.l VSizeOf_idat ; virtual size
dc.l VBaseOf_idat ; virtual address
dc.l FSizeOf_idat ; size of raw data
dc.l FBaseOf_idat ; pointer to raw data
dc.l 0 ; pointer to relocatins
dc.l 0 ; pointer to line numbers
dc.w 0 ; number of relocations
dc.w 0 ; number of line numbers
dc.l $e0000040 ; characteristics
ENDIF

IF UseUdatSection
dc.b '.udat',0,0 ; name
dc.l VSizeOf_udat ; virtual size
dc.l VBaseOf_udat ; virtual address
dc.l FSizeOf_udat ; size of raw data
dc.l FBaseOf_udat ; pointer to raw data
dc.l 0 ; pointer to relocatins
dc.l 0 ; pointer to line numbers
dc.w 0 ; number of relocations
dc.w 0 ; number of line numbers
dc.l $e0000080 ; characteristics
ENDIF

NumberOfSections=(@-@a)/40

; ..............................................
; : End of Image Sections Header :
; ..............................................

; characteristics
; 0x00000020 // Section contains code.
; 0x00000040 // Section contains initialized data.
; 0x00000080 // Section contains uninitialized data.
; 0x00000200 // Section contains comments or some other type of information.
; 0x00000800 // Section contents will not become part of image.
; 0x00001000 // Section contents comdat.
; 0x01000000 // Section contains extended relocations.
; 0x02000000 // Section can be discarded.
; 0x04000000 // Section is not cachable.
; 0x08000000 // Section is not pageable.
; 0x10000000 // Section is shareable.
; 0x20000000 // Section is executable.
; 0x40000000 // Section is readable.
; 0x80000000 // Section is writeable.

; +--------------------------------------------+
; | End of Windows Header |
; +--------------------------------------------+

evencom FileAlignment

SizeOfHeaders==@@

;#==================================================================#
;# End of Headers #
;#==================================================================#

;#==================================================================#
;# Start of Sections #
;#==================================================================#

; +--------------------------------------------+
; | Start of .text Section |
; +--------------------------------------------+

FBaseOf_text==@@
VBaseOf_text==(@-ImageBase+SectionAlignment-1)/SectionAlignment*SectionAlignment
BaseOfCode==VBaseOf_text
@=ImageBase+VBaseOf_text


; ..............................................
; : Start of Thunk Table :
; ..............................................


iat_start=@-ImageBase

USER32_thunk:
MessageBoxA:: dc.l USER32_MessageBoxA -ImageBase
dc.l 0

KERNEL32_thunk:
ExitProcess:: dc.l KERNEL32_ExitProcess -ImageBase
GetStdHandle:: dc.l KERNEL32_GetStdHandle -ImageBase
ReadFile:: dc.l KERNEL32_ReadFile -ImageBase
WriteFile:: dc.l KERNEL32_WriteFile -ImageBase
dc.l 0


iat_size=@-ImageBase-iat_start

; ..............................................
; : End of Thunk Table :
; ..............................................


; ..............................................
; : Start of Import Directory :
; ..............................................


imp_start==@-ImageBase

imp:

dc.l USER32_import -ImageBase
dc.l 0
dc.l 0
dc.l USER32_name -ImageBase
dc.l USER32_thunk -ImageBase

dc.l KERNEL32_import -ImageBase
dc.l 0
dc.l 0
dc.l KERNEL32_name -ImageBase
dc.l KERNEL32_thunk -ImageBase

dc.l 0
dc.l 0
dc.l 0
dc.l 0
dc.l 0

imp_size==@-imp

; ..............................................
; : End of Import Directory :
; ..............................................

USER32_name:
dc.b 'USER32.dll',0
even

USER32_import:
dc.l USER32_MessageBoxA -ImageBase
dc.l 0
even

USER32_MessageBoxA:
dc.w 0
dc.b 'MessageBoxA',0
even


KERNEL32_name:
dc.b 'KERNEL32.dll',0
even

KERNEL32_import:
dc.l KERNEL32_ExitProcess -ImageBase
dc.l KERNEL32_GetStdHandle -ImageBase
dc.l KERNEL32_ReadFile -ImageBase
dc.l KERNEL32_WriteFile -ImageBase
dc.l 0
even

KERNEL32_ExitProcess:
dc.w 0
dc.b 'ExitProcess',0
even
KERNEL32_GetStdHandle:
dc.w 0
dc.b 'GetStdHandle',0
even
KERNEL32_ReadFile:
dc.w 0
dc.b 'ReadFile',0
even
KERNEL32_WriteFile:
dc.w 0
dc.b 'WriteFile',0
even

; ..............................................
; : Start of Code :
; ..............................................


label_block
seg32


winmain::

loop: bsr.l getc ; get char from stdin
cmp.l #-1,r0 ; EOF
bne.b _10 ; branch if not
moveq.l #0,-(sp)
jsr.l (ExitProcess) ; exit program
_10: cmp.b #'A',r0
blo.b _20
cmp.b #'Z',r0
bhi.b _20
add.b #'a'-'A',r0
_20: bsr.l putc ; write char to stdout
br.b loop ; go on


putc: move.l r0,-(sp)
move.b r0,_buf
eor.l r0,r0
add.l _handle,r0
bne.b _10
moveq.l #-11,-(sp)
jsr.l (GetStdHandle)
move.l r0,_handle
_10: moveq.l #0,-(sp)
move.l #_count,-(sp)
moveq.l #1,-(sp)
move.l #_buf,-(sp)
move.l r0,-(sp)
jsr.l (WriteFile)
or.l r0,r0
bne.b _20
_30: moveq.l #0,-(sp)
move.l #_text,-(sp)
move.l #_text,-(sp)
moveq.l #0,-(sp)
jsr.l (MessageBoxA)
moveq.l #0,-(sp)
jsr.l (ExitProcess)
_20: cmp.l #1,_count
bne.b _30
move.l (sp)+,r0
rts.l

_buf: dc.b 0
_text: dc.b 'write error',0
even4
_handle:dc.l 0
_count: dc.l 0


getc: eor.l r0,r0
add.l _handle,r0
bne.b _10
moveq.l #-10,-(sp)
jsr.l (GetStdHandle)
move.l r0,_handle
_10: moveq.l #0,-(sp)
move.l #_count,-(sp)
moveq.l #1,-(sp)
move.l #_buf,-(sp)
move.l r0,-(sp)
jsr.l (ReadFile)
or.l r0,r0
bne.b _20
moveq.l #0,-(sp)
move.l #_text,-(sp)
move.l #_text,-(sp)
moveq.l #0,-(sp)
jsr.l (MessageBoxA)
moveq.l #0,-(sp)
jsr.l (ExitProcess)
_20: movu.bl _buf,r0
cmp.l #1,_count
beq.b _30
move.l #-1,r0
_30: rts.l

_buf: dc.b 0
_text: dc.b 'read error',0
even4
_handle:dc.l 0
_count: dc.l 0


; ..............................................
; : End of Code :
; ..............................................

VSizeOf_text==@-Imagebase-VBaseOf_text
@a=@
evencom FileAlignment
@=@a

FSizeOf_text==@@-FBaseOf_text
SizeOfCode==FSizeOf_text


; +--------------------------------------------+
; | End of .text Section |
; +--------------------------------------------+


; +--------------------------------------------+
; | Start of .idat Section |
; +--------------------------------------------+


FBaseOf_idat==@@
VBaseOf_idat==(@-ImageBase+SectionAlignment-1)/SectionAlignment*SectionAlignment
BaseOfData==VBaseOf_idat
@=ImageBase+VBaseOf_idat

; Insert initialized variables here (and set UseIdatSection=1
; at the top of this file). Because the code section is set
; r/w-able, you can put initialized variables also into the
; code section.

; var1: dc.l 0
; var2: dc.l $12345678

VSizeOf_idat==@-Imagebase-VBaseOf_idat
@a=@
evencom FileAlignment
@=@a
FSizeOf_idat==@@-FBaseOf_idat

; +--------------------------------------------+
; | End of .idat Section |
; +--------------------------------------------+

SizeOfInitializedData==FSizeOf_idat


; +--------------------------------------------+
; | Start of .udat Section |
; +--------------------------------------------+


FBaseOf_udat==@@
VBaseOf_udat==(@-ImageBase+SectionAlignment-1)/SectionAlignment*SectionAlignment
@=ImageBase+VBaseOf_udat

; Insert uninitialized variables here (and set UseUdatSection=1
; at the top of this file). Because the code section is set
; r/w-able, you can put uninitialized variables also at the END
; of the code section.

; buf1: blk.l 10
; buf2: blk.l 200

VSizeOf_udat==@-Imagebase-VBaseOf_udat
@a=@
evencom FileAlignment
@=@a
FSizeOf_udat==@@-FBaseOf_udat

; +--------------------------------------------+
; | End of .udat Section |
; +--------------------------------------------+

SizeOfUninitializedData==VSizeOf_udat
SizeOfImage==(@-ImageBase+SectionAlignment-1)/SectionAlignment*SectionAlignment


;#==================================================================#
;# End of Sections #
;#==================================================================#

Matt Taylor

unread,
Jan 24, 2004, 4:49:43 AM1/24/04
to
"Herbert Kleebauer" <kl...@unibwm.de> wrote in message
news:4012326...@unibwm.de...
<snip>

> But even if an Intel 32 bit processor is used, a beginner always
> should start learning assembly programming in real or V86 mode and
> not in protected mode. The language of the processor is the same
> but the interface to the operating system (int 21 or even BIOS) is
> much simpler than the Win32 interface. And you can use almost all
> 32 bit instructions and addressing modes also in real/V86 mode.
> The only restriction is the limit of 64k memory (without using
> segmentation) which surely isn't a limitation for learning
> assembly programming.
<snip>

Making an interrupt is simpler than call _getc or call _malloc? I think not.

32-bit code has the simplicity of not having to use specific registers in
its addressing modes. Also, flat memory is far less confusing than segmented
memory. Moreover, debugging Win32/Linux code is a lot simpler. I have done
both. I do not miss the days of DOS.

-Matt


Matt Taylor

unread,
Jan 24, 2004, 4:58:15 AM1/24/04
to
"Dpak Cherian" <dpakc...@fastmail.fm> wrote in message
news:476dbfa6.04012...@posting.google.com...
> in 16-bit assembly is there any way to accept numbers as input and display
them.
> btw, is there anything like cin & cout in assembly

Everything eventually becomes machine code. While there are no simple
statements in assembly that do what cin & cout do, there are none in C/C++
either. When you write "cout << endl;", you are making a function call. The
same can be done in assembly. I would recommend looking at the code your
compiler produces. If you use GCC, try this:

g++ -S input.cpp -o input.s

-Matt


Randall Hyde

unread,
Jan 24, 2004, 11:54:59 AM1/24/04
to

"Matt Taylor" <pa...@tampabay.rr.com> wrote in message
news:ZbrQb.94346$873.1...@twister.tampabay.rr.com...

Well, you *can* have cout and cin in your DOS assembly code.
All you need is the appropriate library code and macro support.
Here's a following sample program I created with MASM v6.11a
(the suffix is important here) using the UCR Standard Library v2.0:

var
enum colors,<red,green,blue>
colors c1, c2

endvar

Main proc

mov ax, dseg
mov ds, ax
mov es, ax

MemInit
InitExcept
EnableExcept
finit

try

cout "Enter two colors:"
cin c1, c2
cout "You entered ",c1," and ",c2,nl

.if c1 == red

cout "c1 was red"

.endif

except $Conversion

cout "Conversion error occured",nl

except $Overflow

cout "Overflow error occured",nl

endtry
CleanUpEx

ExitPgm ;DOS macro to quit program.

Main endp


The only problem with this code is the fact that the
macro package in the UCR Standard Library v2.0
exploited some "features" in MASM v6.11a that
went away when MASM v6.11d came along.
It was exactly this kind of trouble (plus the fact that
the macros weren't very robust when there was a
syntax error in their use) that convinced me to write
the High-Level Assember.

Of course, in HLA (the High Level Assembler), the
macro facilities are a bit better and you can do all
kinds of neat things concerning I/O. E.g.,

program demo;
#include( "stdlib.hhf" )
var
i :int32;
j :uns32;
begin demo;

stdout.put( "Enter values for i & j:" );
try

stdin.get( i, j );
stdout.put( "You entered ", i, " and ", j, nl );

anyexception

stdout.put( "Error inputing the numeric values" nl );

endtry;

end demo;

Yes, having a nice set of macros in assembly language
can make I/O just as easy as a high-level language. This
is much better than INT 21h or API calls.

The drawback, of course, is that HLA is 32-bit based
and runs under Win32 or Linux, not DOS (then again,
some consider the fact that they don't have to learn
an obsolete OS API set to be an advantage). The
advantage is that this code compiles and runs unchanged
on either Linux or Windows - something you don't get
when you make OS API calls.
Cheers,
Randy Hyde

Mr Dygi

unread,
Jan 24, 2004, 12:59:38 PM1/24/04
to
Herbert Kleebauer <kl...@unibwm.de> wrote in news:4012326...@unibwm.de:

> But even if an Intel 32 bit processor is used, a beginner always
> should start learning assembly programming in real or V86 mode and
> not in protected mode.

Could you tell me in few words what a different in using real/protected
mode or V86 (?). What V86 is?

--
pozdr. Dygi [GG 1027078]
dygimail(at)poczta(dot)fm

Herbert Kleebauer

unread,
Jan 24, 2004, 4:23:32 PM1/24/04
to
Mr Dygi wrote:
>
> > But even if an Intel 32 bit processor is used, a beginner always
> > should start learning assembly programming in real or V86 mode and
> > not in protected mode.
>
> Could you tell me in few words what a different in using real/protected
> mode or V86 (?). What V86 is?

Maybe Beth can do this. But in order to learn assembly
programming, you have to read the processor manual anyhow:

http://developer.intel.com/design/pentium4/manuals/245471.htm

Beth

unread,
Jan 24, 2004, 6:00:50 PM1/24/04
to

Theoretical bit:

There isn't anything like "cin" / "cout" in assembly; Assembly
language is simply a human-readable form of the CPU's actual
"language"...the _real_ instructions that the CPUs processes...there's
no "abstraction" applied, _except_ for re-writing it as human-readable
text (the CPU actually sees just "binary numbers" :) so that _people_
can actually _use_ it more happily and comfortably than sifting
through tons of numbers all day long...

High-level languages, like C++, "abstract" away from the actual
machine-specifics and are more "problem-orientated" than
"machine-orientated" (though, actually, as an aside, C / C++ is the
HLL that tends to do this _least_..."cin" / "cout" are, of course,
merely "standard additions" in the "standard library" with C++ and, in
fact, even C++ doesn't really have these things "built-in"
either...but if you didn't "#include" the right header file then even
C++ doesn't actually have "cin / cout" as _part of the language_
either...it has them as "standard additions" in the packaged libraries
that usually come along with a C++ compiler :)...so, they like to
provide these kinds of things to help a programmer with their
"problem"...

Assembly language, though, is "machine-orientated"...basically because
assembly language _IS_ the machine, so to speak...or, at least, it's a
human-readable equivalent to the machine instructions that will
finally go through the CPU (i.e. it looks different but, to all
intents and purposes, assembly language is equivalent to machine code
for most of our purposes)...unlike high-level languages, which
"abstract" away from the machine and move more towards the so-called
"problem domain" (defining things in terms of the problem itself
rather than in the terms the machine actually sees things), assembly
language by its nature, _reflects_ the true nature of the CPU and the
system...

And in hardware terms, the keyboard and monitor (for input and output)
are _separate_ items from the CPU...hence, the CPU has no "keyboard"
or "monitor" instructions because those are separate hardware
devices...in assembly language, you control the _CPU_ by talking
directly to it...all other hardware is controlled by instructing the
CPU to "talk" to the other hardware...it's done "indirectly" via the
CPU...there are no "keyboard" instructions but there are instructions
to tell the CPU to send data to other hardware and mechanisms for
accepting data back...or, alternatively, there are instructions to
call into OS or BIOS services which can do the actual low-level
hardware interfacing on behalf of the application...usually used to
provide "portable" access to hardware or simply because they are
easier, comparable to calling C functions like "printf" to do the
same...the following gives a basic practical "starting point" for
looking further into this subject, by covering some of the basic DOS
I/O functions...hardly "comprehensive" but intended to give a basic
set of illustrative examples in how to go about this, from which you
can Hopefully get a reasonable idea of what's going on to be able to
search through "HelpPC" or Ralf Brown's list or some other resources
yourself and being to know what to do and what to expect...

Practical bit:

[ As you've not specified OS or assembler, then the following example
code is for DOS using MASM / TASM syntax, as the most likely
combination you'd probably need :) ]

1. Download "HelpPC" and unzip it somewhere useful on your hard drive:

http://cs.nyu.edu/~yap/classes/machineOrg/helppc/helppc21.zip

2. Run "HelpPC.com"...

3. Select the "Interrupt Services" menu option...

4. Select the "DOS functions" item in the next menu...

5. The DOS functions of interest (that is, that I actually go on with
examples in this post...they are all "interesting" for some purpose
and you might want to look them over and see if you can get them to
work on your own, once you've got a "handle" on how these basic ones
work to give you the basic pattern :) in this list are:

High-level functions:
INT 21h, AH = 09h: Print String
INT 21h, AH = 0Ah: Buffered Keyboard Input (with echo)

[ These functions deal with complete strings under DOS's control; Easy
to use but can't be "customised" much so you have to accept however
DOS deals with the user I/O... ]

Low-level functions:
INT 21h, AH = 01h: Keyboard Input with Echo
INT 21h, AH = 02h: Display Output

[ These functions only deal with I/O of individual characters; Can be
called repeatedly with your own code managing the individual
characters into complete strings itself...useful if you need
functionality that's not provided by the "high-level" functions
above - e.g. printing strings with a "$" sign inside them or providing
"non-standard" input facilities - because you can take more control by
using individual character I/O and handling the rest yourself in your
own code :) ]

5a. The DOS "Print String" function (INT 21h, AH = 09h) prints out a
string of characters, pointed to by DS:DX, up to the first dollar sign
("$") it finds in that string, to the "stdout" device...

Example of use (MASM / TASM syntax):

Print.asm
---------------- 8< ------------------

.model tiny

.data

MyString db "Hello, World!$"

.code

org 100h

; Print string passing the
; address of our "$"-terminated
; string in DS:DX...
;
_start: mov ah, 09h
mov dx, offset MyString
int 21h

; Exit back to DOS prompt
;
mov ah, 4Ch
int 21h

end _start

---------------- >8 ------------------

Note that the address of the string is DS:DX, not just DX...but the DS
segment register is automatically pointing to the right place in a
..COM file, so it doesn't need to be set in this example...

As it writes to "stdout", which is the console by default, but this
may be "redirected" using the standard DOS methods...for example,
"Print.com > Hello.txt" will redirect the output of the program into
the "Hello.txt" file by using the ">" DOS command to change "stdout"
to a file...

5b. The DOS "Buffered Keyboard Input" function (INT 21h, AH = 0Ah)
accepts the address to a specially-formatted "buffer" in the DS:DX
register pair...and then DOS takes over the control of input until the
ENTER key is pressed (maximum buffer size: 255 bytes, minimum buffer
size: 1 byte :)...input is read from "stdin" and the function won't
accept more characters than is specified as the "max character
count"...DOS editing keys are available with the function...

The buffer is of the following format (use fixed pitch font to view):

+-------+-------+---------------------------------------+
| Max | Count | Buffer (N bytes) |
+--/|\--+--/|\--+--/|\----------------------------------+
| | |
| | +--- Input buffer (N bytes)
| | (returns actual input when input complete)
| |
| +----------- Number of characters returned (byte)
| (returned by function when input complete)
|
+------------------- Maximum number of characters to be read
(byte)
(specified to function to define the maximum
amount of characters in buffer; That is,
this
value defines the size of "N bytes" to the
function and is placed in the buffer
_before_
calling the function)


Example of usage (MASM / TASM syntax):

BufInput.asm:
---------------- 8< ------------------

.model tiny

MAX_CHARACTERS equ 12

.data

Buffer db MAX_CHARACTERS
db ?
db MAX_CHARACTERS dup (?)

.code

org 100h

; Call buffered keyboard input
; passing the address of our
; buffer in DS:DX...
;
_start: mov ah, 0Ah
mov dx, offset Buffer
int 21h

; Exit back to DOS prompt...
;
mov ah, 4Ch
int 21h

end _start

---------------- >8 ------------------

Note that the address of the string is DS:DX, not just DX...but the DS
segment register is automatically pointing to the right place in a
..COM file, so it doesn't need to be set in this example...

Input is taken from "stdin" and output is written to "stdout"...either
or both may be "redirected" using the standard DOS mechanisms...for
example, "bufinput > input.txt" will "echo" the input to the
"input.txt" file (input won't be visible as it's gone to the
file)...and then "bufinput < input.txt" will read the input from the
"input.txt" file and redirect it to the screen (previous input can now
be read back out of the file and "echoed" onto the screen)...and then
"bufinput < input.txt > output.txt" will read in from "input.txt" and
echo the input to "output.txt" (effectively, just copying it from one
file to the other :)...

[ Be careful of this redirection in that if you supply a file that
doesn't have a proper terminator, the DOS function simply sits waiting
for one, which will never come because it's not in the file...and
pressing the keyboard ENTER is useless because, now that it's
"redirected", the program isn't looking to the keyboard for input
anymore so never gets the message...and, therefore, the program waits
forever :( ]

5c. The DOS "Display Output" function (INT 21h, AH = 02h) simply
prints out the character specified in the DL register to "stdout"...

Example of usage (MASM / TASM syntax):

Print2.asm:
---------------- 8< ------------------

.model tiny

.data

MyString db "Micro$oft $uck$!", 0

.code

org 100h

; Call custom "Print" routine
; passing address of string in
; DS:SI...
;
_start: mov si, offset MyString
call Print

; Exit back to DOS prompt...
;
mov ah, 4Ch
int 21h

; Print:
;
; DS:SI = offset to zero-terminated ASCII string
;
Print: mov ah, 02h ; Select DOS "Display output"
function
NextChar: mov dl, [ si ] ; Grab byte from SI
cmp dl, 00h ; Have we reached end of string?
je EndOfPrint ; Yes, then jump out of loop
int 21h ; Print character to "stdout"
inc si ; Increment SI to move to next
character
jmp NextChar
EndOfPrint: ret

end _start

---------------- >8 ------------------

Note how I've created a custom "Print" routine using this "low-level"
function that uses a zero byte to specify the end of the string,
rather than DOS's usual "$" terminator in their "high-level" print
string function...the string to be printed has been suitably decorated
with plenty of "$" signs to demonstrate this (apologies for to
Microsoft fans ;)...

Of course, you need not write any "custom" routine this way (or at
all, even ;) and you can do anything you like...that is the beauty of
these "low-level" DOS functions in comparison to the "high-level"
ones...this function just spits out a character to "stdout" and
nothing else...it's up to your own code to use this function how you
see fit...for clever and devious purposes, no doubt ;)...

Another possibility, for example, is to use Pascal-like strings where
the first byte specifies the size of the string (and isn't printed)
and there isn't a "terminator" on the string at all (similar to that
"buffered input" function earlier, in a sense...except there's only a
single "max" figure because a "count of characters input" doesn't make
sense for an output-only function :)...

Alternative example of usage (MASM / TASM syntax):

Pascal.asm:
---------------- 8< ------------------

.model tiny

.data

MyString db 22
db "A Pascal-style string!"

.code

org 100h

; Call custom "PascalPrint"
; routine passing address of
; Pascal-style string in
; DS:SI...
;
_start: mov si, offset MyString
call PascalPrint

; Exit back to DOS prompt...
;
mov ah, 4Ch
int 21h

; PascalPrint:
; DS:SI = offset to zero-terminated ASCII string
;
PascalPrint: mov ah, 02h ; Select DOS "Display output"
function
mov cl, [ si ] ; Grab "count of characters" into CL
inc si ; Advance to start of actual string
NextChar: mov dl, [ si ] ; Grab character from string
int 21h ; Print it to "stdout"
inc si ; Advance to next character
dec cl ; Decrement count
jnz NextChar ; Jump back to print next character
if
; not at end of string yet
ret

end _start

---------------- >8 ------------------

This shows how, though the "low-level" functions don't offer as much
functionality, this is actually useful for creating "custom" print
routines...

Note, output can be redirected - just as before - using the DOS ">"
mechanism...for example, "Pascal > Pascal.txt" writes the string to
the file "Pascal.txt"...

5d. The DOS "Keyboard Input with Echo" function (INT 21h, AH = 01h)
waits for a character to be input on "stdin" and then "echoes" that
character to "stdout"...

Example of usage (MASM / TASM syntax):

Input.asm:
---------------- 8< ------------------

.model tiny

MAX_CHARACTERS equ 12

.data

Buffer db MAX_CHARACTERS
db MAX_CHARACTERS dup (?)

.code

org 100h

_start: mov di, offset Buffer
call Input

; Exit back to DOS prompt...
;
mov ah, 4Ch
int 21h

; Input:
;
; DS:DI = offset to input buffer
; (first byte specifies size)
;
Input: mov ah, 01h ; Select DOS "Input with echo"
function
mov cl, [ di ] ; Grab size of buffer into CL (max
size)
mov ch, cl ; Copy into CH (current count)
inc di ; Advance to start of actual
buffer
NextChar: int 21h ; Input character from "stdin"
cmp al, 0Dh ; Is it ENTER?
je EndOfInput ; Yes, then terminate early
cmp al, 08h ; Is it backspace?
jne CarryOn ; No, then skip over backspace
processing

cmp ch, cl ; Are we at the start of the
buffer?
je NextChar ; Yes, ignore backspace as we
can't go back
; before the beginning of the
buffer
dec di ; Move back a character in the
buffer
inc ch ; Increment count back up
mov ah, 02h ; Select DOS "display output"
mov dl, 20h ; A space to clear old character
int 21h ; Print it!
mov dl, 08h ; A backspace character moves left
; (non-destructive)
int 21h ; Print it!
mov ah, 01h ; Restore DOS "input with echo"
function
jmp NextChar ; Jump to get next character

CarryOn: mov [ di ], al ; Store input into buffer
inc di ; Advance to next character in
buffer
dec ch ; Decrement count of characters
jnz NextChar ; While there's still room in
buffer,
; do it all again
EndOfInput: ret

end _start

---------------- >8 ------------------

This custom "input" routine is a little bit more complicated than the
others so far, due to the unique problem of the backspace character
(allowing the last character - _IF_ there's a last character - to be
"undone" :)...to be honest, this _isn't_ the best input routine you'll
ever see...but input is always inherently a little more complicated
because the user could type practically anything and we have to
account for it all...I've bothered to deal with the "backspace" key to
give you an appreciation of what I mean by the added complexity just
this one "undo" key adds to the input routine (we now need _two_
"count" variables - in CH and CL - to handle the "special case" of
backspace when the buffer is actually empty, which, of course, should
just be ignored as things could go dreadfully, dreadfully wrong if you
allowed a user to backspace passed the beginning of the buffer! ;)...

I make no guarantees about the "redirection" - because I didn't write
it taking that into account - but I just ran a simple test or two and
it _seemed_ to work okay...it's probably better NOT to use the "echo"
input DOS function, more generally, for this...but something like
"input without echo" (INT 21h, AH = 07h), which works just like this
function _without_ the "echo" to "stdout", though...and then use
"display output" (INT 21h, AH = 02h) to only print things that are
valid, if you need better control over that...

Because though you may not see it _visibly_ when you look at the
output of a "redirected" file (as the backspace character is being
_performed_ as part of the output of the file :), if you put it into a
hex viewer, you can actually see "20h 08h" (space backspace...the
"hack" used to make the input look right on the screen by wiping out
the old characters with a space when you tap backspace) characters in
the output file(!!)...which would _look_ okay (and the actual contents
of the buffer will be okay too, so they'd be no problems with the
variables inside the program :) but any comparison of the redirected
"Hello, world" to "Hello(space backspace)o, world" would clearly not
give a "match"...this problem, though, won't effect the program at all
when things aren't redirected...the problem is basically that
"backspace" literally moves backwards and wipes things out on the
screen, as we want, but just gets written to a _file_ like any other
character when redirected...this is a particularly tricky
problem...perhaps, simply, don't "redirect" any of the input (don't
write to "stdout") but use some "direct console" output function which
_forces_ things onto the screen without redirection and then "echo"
out the _finished_ input when ENTER is pressed...

Like I was saying, input - because the user is permitted to hit _any_
key they like on the keyboard at any point (even if it's really
annoying that they are doing silly things like trying to backspace
passed the start of the buffer, silly users! ;) - is an inherently
more complicated problem...I've given a "taste" of how to go about
solving these types of problems in the example but don't take the
example above as "role model" code to "cut and paste" into other
programs...it's "purely illustrative" because even _I_ wouldn't trust
that quick and nasty "hack" with any important user input, anyway
;)...

The benefit, of course, of the "low-level" input function over the
"high-level" one is much the same as it was with the output
functions...you get better "control" over input and can write custom
input routines...you could, for instance, use these functions to
create an input routine that only accepts hex characters or decimal
floating-point numbers (giving a "beep" if something invalid is typed
;) or that allows using the TAB key for moving around between "fields"
in a "form" (pretending that you're in a GUI...although, that makes
the already complicated "input" problem even more confusing because
you've got to handle multiple input fields at the same time and, at
the drop of a hat, allow the user to move back and forth
between...but, if you want real "user-friendliness" people are so used
to this ability from GUIs that anything less tends to kind of
"disappoint" your users ;) or whatever...

Of course, now that you've downloaded the handy "HelpPC" program,
which neatly divides up lots of ASM, DOS and BIOS stuff into nice
menus, you can just "browse" and try out code using the functions and
stuff...see what happens...

You can also grab Ralf Brown's Interrupt List from:

http://www.cs.cmu.edu/afs/cs/user/ralf/pub/WWW/files.html

Which is even more comprehensive (but, thus, a little more difficult
to search than "HelpPC" :) and is indispensable if you're programming
in DOS...

Beth :)


August Derleth

unread,
Jan 24, 2004, 9:17:44 PM1/24/04
to
Herbert Kleebauer wrote:
> "Brandon J. Van Every" wrote:
>
>
>>I'm slightly curious why you care about 16-bit ASM in the modern day.
>>Actually, I'm not curious, that's the wrong word. I'm saying you shouldn't
>>be bothering with 16-bit ASM for any reason. 32-bit is minimum.
>
>
> There are still much more 4/8 bit processors sold than 16/32/64 processors.

I'd like a citation for this claim. Are seriously tiny embedded systems
truly that common?

> But even if an Intel 32 bit processor is used, a beginner always
> should start learning assembly programming in real or V86 mode and
> not in protected mode.

Should all new drivers start out with a Model-T, too? Or all new pilots
start off with a biplane?

No, I simply cannot agree with this statement. It's wrong, and will lead
to scaring off more people from assembly than is really needed. Intel
botched the 16-bit generation completely, and nothing can convince me
that it's better to start with that generation of chips (or an emulation
thereof).

> The language of the processor is the same
> but the interface to the operating system (int 21 or even BIOS) is
> much simpler than the Win32 interface.

That's a failing of Win32, not 32-bit chips. All of my 32-bit assembly
programming is for Linux, and Linux has a DOS-like interrupt-driven
kernel interface, but it's much more convenient simply because you don't
need to beat your head against a wall simply to do things like forking.

(Plus, in Linux you can use libc and all of the other C libraries your
system comes with. Which is damned simpler than reinventing the wheel,
especially for new programmers, not to mention giving new assembly
programmers experience in a very valuable area: interfacing with C code,
either calling it or being called by it.)

Besides, I do write 32-bit code for DOS. I target FreeDOS, but MS-DOS
3.x and later all ran on 32-bit chips.

In short, wanting to use a specific OS and/or API style (even one as
ancient as DOS) is no reason to stick with 16-bit Intel chips.

> And you can use almost all
> 32 bit instructions and addressing modes also in real/V86 mode.

Then why, pray tell, bother with V86 at all? Why not just go 32-bit all
the way and forget about things like segments? (OK, 32-bit chips have
segments. 4 Gibibyte segments. And if you need more RAM than that, why
the hell are you writing in assembly?)

> The only restriction is the limit of 64k memory (without using
> segmentation) which surely isn't a limitation for learning
> assembly programming.

I disagree: It's a rationalization for using a broken system, and it
will cripple new assembly programmers until they finally move on to
semi-modern chips. 4 Gibibytes seems tiny now that 64-bit chips are
coming down from Mount Server, but 4 Gibibytes is more than enough for
small programs at the moment. 64 Kibibytes /is not/.

>
> As an example a simple program which reads from stdin and writes
> to stdout, converting all upper case characters to lower case.
> To make it compatible with the win32 version, it uses mostly
> 32 bit instructions. But even then the generated executable
> file size is only 109 bytes.

Executable size? Dick-waving nonsense. Blocks on a hard drive are larger
than that. You gain nothing by stripping the binary to less than one or
two Kibibytes.

I notice you /aren't even using 8088 opcodes/. Post-increment indexing
modes? I guess it's the 68000, if it's a microprocessor, but it could
(possibly) be a PDP or a VAX.

I'm aware that this was cross-posted to alt.lang.asm. But why would you
hype V86 and other Intel things if your code wasn't even going to be for
Intel chips?

Matt Taylor

unread,
Jan 24, 2004, 10:53:18 PM1/24/04
to
"August Derleth" <s...@sig.now> wrote in message
news:XWEQb.6301$dF4....@fe02.usenetserver.com...
<snip>

> > The language of the processor is the same
> > but the interface to the operating system (int 21 or even BIOS) is
> > much simpler than the Win32 interface.
>
> That's a failing of Win32, not 32-bit chips. All of my 32-bit assembly
> programming is for Linux, and Linux has a DOS-like interrupt-driven
> kernel interface, but it's much more convenient simply because you don't
> need to beat your head against a wall simply to do things like forking.

What is true for Linux is also true for Win32. System calls are done via
interrupts and are quite convenient. Most Win32 functions aren't horribly
daunting, and it is also possible to call the C runtime functions which are
probably more familiar to some.

<snip>

More likely someone took PDP/VAX as a starting point and grafted x86 onto
it. The pre-decrement and post-increment indexing correspond to push/pop
instructions. The trap mneumonic replaces the int mneumonic. Other analogues
are apparent as well (such as DOS functions being called).

-Matt


Herbert Kleebauer

unread,
Jan 25, 2004, 6:31:57 AM1/25/04
to
August Derleth wrote:
> Herbert Kleebauer wrote:

> > But even if an Intel 32 bit processor is used, a beginner always
> > should start learning assembly programming in real or V86 mode and
> > not in protected mode.
>
> Should all new drivers start out with a Model-T, too?

I didn't speak of an ancient 8086 processor. Even the newest x86 processor
supports the three modes: real/V86/protected mode. And you can use the
32 bit instructions and all the 32 bit addressing modes in any of this
three modes. So it doesn't matter at all which of this modes you use to
LEARN assembly programing. But it is important to use an operating
system with a simple interface so you can concentrate on the language
of the processor and don't have to spend much more time with the OS
interface than with the processor instructions. And the int21
interface is much easier to use (and still supported in the newest
MS operating systems for V86 mode) than the Win32 interface.

Now to your example, how to learn to drive a car. Nobody says you
should use a Model-T, use the a modern car (X86). But do you think a
beginner should start in the rush hour in the streets of New York
(Windows interface)? Wouldn't it be much better to use a street
without public traffic ("DOS", which doesn't really mean DOS,
but the int21 interface for v86 programs in Windows). Then you
can concentrate on your car and needn't to worry about all
the other things happening on the streets of NY. Maybe this
empty street is only a few miles (64 kbyte) instead of the
hundreds of miles of streets in NY (4 Gbyte), but that is enough
to learn all about your car. And once you are familiar with your
car you can start to drive through NY.



> No, I simply cannot agree with this statement. It's wrong, and will lead
> to scaring off more people from assembly than is really needed. Intel
> botched the 16-bit generation completely, and nothing can convince me
> that it's better to start with that generation of chips (or an emulation
> thereof).

Sorry, but I don't understand how a easy to use OS interface
can scare off people. If you look at a piece of code without
an OS call, you can't decide if this is code for V86 or
protected mode. V86 is not only the emulation of an 8086, it
supports the same 32 bit addressing modes as protected mode.


> > The language of the processor is the same
> > but the interface to the operating system (int 21 or even BIOS) is
> > much simpler than the Win32 interface.
>
> That's a failing of Win32, not 32-bit chips. All of my 32-bit assembly
> programming is for Linux, and Linux has a DOS-like interrupt-driven
> kernel interface, but it's much more convenient simply because you don't
> need to beat your head against a wall simply to do things like forking.

Learning assembly programming and learning the interface of an OS
are two total different things. You only need a minimal OS interface
for learning assembly programming (read/write files, read keyboard,
write to screen in text/graphics mode). And there is no simpler way
than using the DOS interface (which is also present in the newest
Windows version). After you have learned assembly programing, you
can decide which OS (Windows/Linux) you would like to use to write
applications in assembler and then learn the API of this OS.

> (Plus, in Linux you can use libc and all of the other C libraries your
> system comes with. Which is damned simpler than reinventing the wheel,
> especially for new programmers, not to mention giving new assembly
> programmers experience in a very valuable area: interfacing with C code,
> either calling it or being called by it.)

Learning assembly programming is to learn to use the instruction set
of the processor to effective solve a given problem. It has
nothing to with calling libraries or interfacing with HLL (that
belongs to learning the HLL).


> > And you can use almost all
> > 32 bit instructions and addressing modes also in real/V86 mode.
>
> Then why, pray tell, bother with V86 at all? Why not just go 32-bit all
> the way and forget about things like segments? (OK, 32-bit chips have
> segments. 4 Gibibyte segments. And if you need more RAM than that, why
> the hell are you writing in assembly?)

If you restrict to 64k then you need no real mode segments. "DOS"
com programs are very similar to Win32 programs, but much easier
to understand and concerning assembly programming you will learn
exactly the same. Just look at the posted example, the main code
is identical, but there is nearly no overhead for the com program.


> > The only restriction is the limit of 64k memory (without using
> > segmentation) which surely isn't a limitation for learning
> > assembly programming.
>
> I disagree: It's a rationalization for using a broken system, and it
> will cripple new assembly programmers until they finally move on to
> semi-modern chips. 4 Gibibytes seems tiny now that 64-bit chips are
> coming down from Mount Server, but 4 Gibibytes is more than enough for
> small programs at the moment. 64 Kibibytes /is not/.

We are speaking about LEARNING assembly programming and for that
purpose 64k are enough. It is a different thing if you want to
write real applications in assembler. But in order to write
applications in assembler you first have to learn assembly programing
which is much easier if you use v86 mode. Besides, nobody will write
applications in assembler any more (that is much more obsolete than
a 8086 processor). Use a HLL and if necessary an inline assembler or
link to small piece of code written in assembler.

> > As an example a simple program which reads from stdin and writes
> > to stdout, converting all upper case characters to lower case.
> > To make it compatible with the win32 version, it uses mostly
> > 32 bit instructions. But even then the generated executable
> > file size is only 109 bytes.
>
> Executable size? Dick-waving nonsense. Blocks on a hard drive are larger
> than that. You gain nothing by stripping the binary to less than one or
> two Kibibytes.

You are right, it doesn't matter how much disc space is needed for
a program. But we are speaking about learning assembly programming.
And it does matter if a beginner has to understand 1000 or only 100
bytes to successfully run his first assembler program.


> I'm aware that this was cross-posted to alt.lang.asm. But why would you
> hype V86 and other Intel things if your code wasn't even going to be for
> Intel chips?

It is x86 code, but I use 32 bit instructions and addressing modes
since more than 10 years now in real/V86 mode.

August Derleth

unread,
Jan 25, 2004, 2:51:37 PM1/25/04
to
Herbert Kleebauer wrote:

> August Derleth wrote:
>
>>Herbert Kleebauer wrote:
>
>
>>>But even if an Intel 32 bit processor is used, a beginner always
>>>should start learning assembly programming in real or V86 mode and
>>>not in protected mode.
>>
>>Should all new drivers start out with a Model-T, too?
>
>
> I didn't speak of an ancient 8086 processor. Even the newest x86 processor
> supports the three modes: real/V86/protected mode. And you can use the
> 32 bit instructions and all the 32 bit addressing modes in any of this
> three modes. So it doesn't matter at all which of this modes you use to
> LEARN assembly programing. But it is important to use an operating
> system with a simple interface so you can concentrate on the language
> of the processor and don't have to spend much more time with the OS
> interface than with the processor instructions. And the int21
> interface is much easier to use (and still supported in the newest
> MS operating systems for V86 mode) than the Win32 interface.

But, as I said, the int 21h interface really isn't tied to any mode. You
can access ah/al and so on even in pure 32-bit mode, and you don't need
to bother with all of the botches of Intel's 16-bit systems.

And if you are using the 32-bit addressing modes and opcodes in V86
mode, why not drop the last pretenses of `simplicity' and move into
32-bit protected mode? It really isn't that difficult, and it can save
you from shooting yourself in the foot: In protected mode, it becomes
impossible to scribble on memory you don't own. What could have been an
OS-corrupting error becomes a much easier to understand segfault error
on Linux, for example, because Linux has nothing to do with V86. (Linux
has a syscall to move a specific process into V86 mode, which to my
knowledge is only used by one program: dosemu, the virtual x86 system
capable of hosting a DOS-like OS plus BIOS. Other than that, Linux is
just another Unix.)

>
> Now to your example, how to learn to drive a car. Nobody says you
> should use a Model-T, use the a modern car (X86). But do you think a
> beginner should start in the rush hour in the streets of New York
> (Windows interface)? Wouldn't it be much better to use a street
> without public traffic ("DOS", which doesn't really mean DOS,
> but the int21 interface for v86 programs in Windows). Then you
> can concentrate on your car and needn't to worry about all
> the other things happening on the streets of NY. Maybe this
> empty street is only a few miles (64 kbyte) instead of the
> hundreds of miles of streets in NY (4 Gbyte), but that is enough
> to learn all about your car. And once you are familiar with your
> car you can start to drive through NY.

And I think protected mode is simpler, and libc more convenient, than
anything DOS has to offer. I can `hop in my car' (forget about
segmenting) and use convenient `routes' (the libc syscalls), replete
with `road maps' (the man pages for those syscalls, which document
syntax, semantics, and expected return values) and the ability to `make
my own roads' (write something in C if it isn't obvious how to do it in
assembly). And writing it in C is a good method of learning how it can
be done, since most C compilers (gcc being one of them) will output
assembly instead of just binaries.

V86 mode isn't a comfy dirt road. It's having to grind the crank on your
engine and distill your own gas from petroleum. And 32-bit protected
mode isn't a complex NYC. It's being able to ignore the engine most of
the time and knowing there's well-paved roads to wherever you most want
to go.

>
>
>>No, I simply cannot agree with this statement. It's wrong, and will lead
>>to scaring off more people from assembly than is really needed. Intel
>>botched the 16-bit generation completely, and nothing can convince me
>>that it's better to start with that generation of chips (or an emulation
>>thereof).
>
>
> Sorry, but I don't understand how a easy to use OS interface
> can scare off people. If you look at a piece of code without
> an OS call, you can't decide if this is code for V86 or
> protected mode. V86 is not only the emulation of an 8086, it
> supports the same 32 bit addressing modes as protected mode.

Here I was wrong: I was still thinking of V86 mode only allowing
8086-style addressing modes and such like. But my later contention
stands: If you're using 32-bit addressing and opcodes, why not use
protected-mode all the way?

>
>
>
>>>The language of the processor is the same
>>>but the interface to the operating system (int 21 or even BIOS) is
>>>much simpler than the Win32 interface.
>>
>>That's a failing of Win32, not 32-bit chips. All of my 32-bit assembly
>>programming is for Linux, and Linux has a DOS-like interrupt-driven
>>kernel interface, but it's much more convenient simply because you don't
>>need to beat your head against a wall simply to do things like forking.
>
>
> Learning assembly programming and learning the interface of an OS
> are two total different things. You only need a minimal OS interface
> for learning assembly programming (read/write files, read keyboard,
> write to screen in text/graphics mode). And there is no simpler way
> than using the DOS interface (which is also present in the newest
> Windows version). After you have learned assembly programing, you
> can decide which OS (Windows/Linux) you would like to use to write
> applications in assembler and then learn the API of this OS.

Actually, I disagree with you here. (As I'm sure you know.) The DOS API
is rather more complex than the libc interface on Linux simply because
libc is more consistent: Whereas DOS makes you memorize how each
register is used by each interrupt, libc simply does everything on the
stack. You push your arguments, make the call, and pop the result. It is
/not/ efficient, and Linux /does/ define a kernel interface which is
very DOS-like, but I think simplicity and consistency are more important
than speed.

(I suspect libc on Win32 is much like that on Linux. It would surprise
me if it were different in important respects.)

>
>
>>(Plus, in Linux you can use libc and all of the other C libraries your
>>system comes with. Which is damned simpler than reinventing the wheel,
>>especially for new programmers, not to mention giving new assembly
>>programmers experience in a very valuable area: interfacing with C code,
>>either calling it or being called by it.)
>
>
> Learning assembly programming is to learn to use the instruction set
> of the processor to effective solve a given problem. It has
> nothing to with calling libraries or interfacing with HLL (that
> belongs to learning the HLL).

/Au contraire/: Assembly isn't a stand-alone language anymore in most
cases. Interfacing with an HLL (and I don't know how HL C is ;) ) is not
only an exercise in simplicity (via libc), it's practice in how to
structure your own subroutines (learn which registers you must save,
learn how to create and destroy a stack frame, learn how to access
arguments, and learn how to properly return a value) and create your own
libraries.

Learning the instruction set isn't hard. Learning memory is more
difficult, but 32-bit protected mode makes it easier in addition to
giving you a nice net. Learning how to structure a program logically and
how to write consistent code that makes use of the environment is more
difficult, and it isn't something DOS is especially good at teaching.

>
>
>
>>>And you can use almost all
>>>32 bit instructions and addressing modes also in real/V86 mode.
>>
>>Then why, pray tell, bother with V86 at all? Why not just go 32-bit all
>>the way and forget about things like segments? (OK, 32-bit chips have
>>segments. 4 Gibibyte segments. And if you need more RAM than that, why
>>the hell are you writing in assembly?)
>
>
> If you restrict to 64k then you need no real mode segments. "DOS"
> com programs are very similar to Win32 programs, but much easier
> to understand and concerning assembly programming you will learn
> exactly the same. Just look at the posted example, the main code
> is identical, but there is nearly no overhead for the com program.

I looked at both examples, and I think the second was rather
over-complex. /None/ of my assembly programs are that complex, given so
simple a task. And if they do become that complex, I write in a
different language. ;)

>
>
>
>>>The only restriction is the limit of 64k memory (without using
>>>segmentation) which surely isn't a limitation for learning
>>>assembly programming.
>>
>>I disagree: It's a rationalization for using a broken system, and it
>>will cripple new assembly programmers until they finally move on to
>>semi-modern chips. 4 Gibibytes seems tiny now that 64-bit chips are
>>coming down from Mount Server, but 4 Gibibytes is more than enough for
>>small programs at the moment. 64 Kibibytes /is not/.
>
>
> We are speaking about LEARNING assembly programming and for that
> purpose 64k are enough. It is a different thing if you want to
> write real applications in assembler. But in order to write
> applications in assembler you first have to learn assembly programing
> which is much easier if you use v86 mode. Besides, nobody will write
> applications in assembler any more (that is much more obsolete than
> a 8086 processor). Use a HLL and if necessary an inline assembler or
> link to small piece of code written in assembler.

Why give a learner a crippled tool when he already owns a fully-featured
one? I say, 32-bit protected mode leaves behind a lot of baggage and
opens new doors of convenience.

Learning on an emulation of an antique is not simpler in this case, it
is simply different, and it brings its own baggage with it. libc may
have baggage from your point of view, but it's the kind of baggage
assembly programmers deal with now and will have to deal with for as
long as humans code in assembly. Besides, learning about the stack is a
nice brain-expander that should help them learn to visualize other data
structures, such as linked lists and hashes.

>
>
>>>As an example a simple program which reads from stdin and writes
>>>to stdout, converting all upper case characters to lower case.
>>>To make it compatible with the win32 version, it uses mostly
>>>32 bit instructions. But even then the generated executable
>>>file size is only 109 bytes.
>>
>>Executable size? Dick-waving nonsense. Blocks on a hard drive are larger
>>than that. You gain nothing by stripping the binary to less than one or
>>two Kibibytes.
>
>
> You are right, it doesn't matter how much disc space is needed for
> a program. But we are speaking about learning assembly programming.
> And it does matter if a beginner has to understand 1000 or only 100
> bytes to successfully run his first assembler program.

I say byte count is less of an issue than consistency. Reduce the number
of concepts they need to master, and they'll be able to create larger
programs sooner. libc is great at managing complexity.

>
>
>
>>I'm aware that this was cross-posted to alt.lang.asm. But why would you
>>hype V86 and other Intel things if your code wasn't even going to be for
>>Intel chips?
>
>
> It is x86 code, but I use 32 bit instructions and addressing modes
> since more than 10 years now in real/V86 mode.

Well, I was wrong here. You did write in a variant of assembly that
could be translated to x86 opcodes, but nothing I'd call 32-bit or even
AT&T syntax. You apparently took PDP syntax and pared it down to work on
the much-simplified x86 instruction set. I've never seen that done
before, and I'd be interested to know which assembler accepts your
source code.

In other words, it's probably logical enough to you and whatever
assembler you use. But it's different enough from every other piece of
x86 code it's nigh-unreadable to 95% of the people here.

August Derleth

unread,
Jan 25, 2004, 2:51:39 PM1/25/04
to
Matt Taylor wrote:

> "August Derleth" <s...@sig.now> wrote in message
> news:XWEQb.6301$dF4....@fe02.usenetserver.com...
> <snip>
>
>>>The language of the processor is the same
>>>but the interface to the operating system (int 21 or even BIOS) is
>>>much simpler than the Win32 interface.
>>
>>That's a failing of Win32, not 32-bit chips. All of my 32-bit assembly
>>programming is for Linux, and Linux has a DOS-like interrupt-driven
>>kernel interface, but it's much more convenient simply because you don't
>>need to beat your head against a wall simply to do things like forking.
>
>
> What is true for Linux is also true for Win32. System calls are done via
> interrupts and are quite convenient. Most Win32 functions aren't horribly
> daunting, and it is also possible to call the C runtime functions which are
> probably more familiar to some.

I suspected as much, but I've never done Win32 programming at the
assembly level.

I was tired at the time, but you must admit it's very odd-looking. My
pattern-detecting brain was thrown for a loop at this point, and it
wasn't until I looked at it now that I finally grasped the similarities.
I'm still not sure which registers his r0-r7 match up with, though (is
r0 eax? is r0 ebx? how does he access ah? etc.). And, of course, I have
no idea which assembler his code is meant for. I think it would be
interesting to know. (What can I say? The predictibility has become
boring. I want to learn a gratuitously different syntax for the same old
ISA. ;) )

>
> -Matt

Jim Higgins

unread,
Jan 25, 2004, 4:52:28 PM1/25/04
to
On Sun, 25 Jan 2004 02:17:44 +0000 (UTC), in
<XWEQb.6301$dF4....@fe02.usenetserver.com>, August Derleth
<s...@sig.now> wrote:

>Herbert Kleebauer wrote:
>
>> But even if an Intel 32 bit processor is used, a beginner always
>> should start learning assembly programming in real or V86 mode and
>> not in protected mode.
>
>Should all new drivers start out with a Model-T, too? Or all new pilots
>start off with a biplane?

The modern alternative to the Model-T is acceptable for a
beginner, but let's not start off in downtown rush hour traffic.
As for the biplane, given a choice for new pilots of a biplane or
a 747, do I take it correctly that you would recommend the 747?

>> The language of the processor is the same
>> but the interface to the operating system (int 21 or even BIOS) is
>> much simpler than the Win32 interface.
>
>That's a failing of Win32, not 32-bit chips. All of my 32-bit assembly
>programming is for Linux, and Linux has a DOS-like interrupt-driven
>kernel interface, but it's much more convenient simply because you don't
>need to beat your head against a wall simply to do things like forking.

A failing of Win32 or not, it is a problem when a beginner has to
spend more time learning the interface than learning to use
assembly language.

>In short, wanting to use a specific OS and/or API style (even one as
>ancient as DOS) is no reason to stick with 16-bit Intel chips.

Did anyone insist on strictly 16-bit hardware? If so I missed
it.

>> And you can use almost all
>> 32 bit instructions and addressing modes also in real/V86 mode.
>
>Then why, pray tell, bother with V86 at all? Why not just go 32-bit all
>the way and forget about things like segments? (OK, 32-bit chips have
>segments. 4 Gibibyte segments. And if you need more RAM than that, why
>the hell are you writing in assembly?)

Since when did the availability of seemingly endless RAM impose a
restriction on using assembly language? You aren't making any
sort of rational case for starting a beginning assembly language
programmer off with Win32 or protected mode programming; you're
just trotting out your own personal preferences.

>> The only restriction is the limit of 64k memory (without using
>> segmentation) which surely isn't a limitation for learning
>> assembly programming.
>
>I disagree: It's a rationalization for using a broken system, and it
>will cripple new assembly programmers until they finally move on to
>semi-modern chips.

Probably so, but you don't start new pilots off in a 747.

>4 Gibibytes seems tiny now that 64-bit chips are
>coming down from Mount Server, but 4 Gibibytes is more than enough for
>small programs at the moment. 64 Kibibytes /is not/.

For a beginning assembly language programmer 64K isn't enough?
Are you serious?

>> As an example a simple program which reads from stdin and writes
>> to stdout, converting all upper case characters to lower case.
>> To make it compatible with the win32 version, it uses mostly
>> 32 bit instructions. But even then the generated executable
>> file size is only 109 bytes.
>
>Executable size? Dick-waving nonsense. Blocks on a hard drive are larger
>than that. You gain nothing by stripping the binary to less than one or
>two Kibibytes.

It isn't a case of stripping the binary. It's a case of writing
the program in assembly language targeting a real mode x86
processor and finding that the compiled machine code totals only
a few hundred bytes. What would you have the programmer do -
insert 10X as many nops as other instructions to bloat it up to
2K? Nobody was arguing smaller is better. The point I got was
that small is the *nature* of beginning assembly language
programs so the availability of a huge address space, and the
actual RAM to fill it is immaterial to the discussion. Nor is it
necessary to wade thru the complexity of learning the interface
to Win32 to write a beginner's assignment involving a bit of file
I/O.

It isn't that real mode is globally better; it's just better in
this limited situation. If the beginner likes assembly language
programming, move him up to the more complex OS platform. But
start him off on the more complex platform and risk losing him as
an assembly language programmer for life.

--
Jim Higgins, quasimodo AT yahoo DOT com
icbm: 33.55.34N, 80.24.21W

John H. Guillory

unread,
Jan 25, 2004, 7:05:00 PM1/25/04
to
On Sat, 24 Jan 2004 17:59:38 +0000 (UTC), Mr Dygi
<dygim...@SPAMpoczta.fm> wrote:

>Could you tell me in few words what a different in using real/protected
>mode or V86 (?). What V86 is?

In order to understand the various modes, you must understand the
history of CPU's.

Intel started long ago with the 4040, which was used only in
calculators. Later, the 8080 was designed and used in CP/M based
systems, then came along the 8088 (and soon after 8086), which was
used on PC's, XT's, and clones. These systems used 16-bit
instructions on what was an 8-bit CPU (or in the case of the 8086 a
16-bit cpu with an 8-bit bus), and in order to access more memory than
possible with a single 16-bit register, Intel used segment:offset
scheme of doing things. The segment was shifted 4 bits and added to
the offset to point to the actual memory location. This meant that
any given memory location could be referenced in several different
ways, eg.


000:400h
is the same as
40h:0h

And many other potential combinations. You had 4 segment registers on
the 8088/8086, CS,DS,ES, and SS. SS was used for the stack, CS for
code, DS for data and ES was an extra register often used with data
for copying to/from one location to another. The 8088 could access a
whole whopping 1meg of memory this way. Along came the 80286 and with
it the ability to access 16 megs, but to do so the 80286 had to forget
about the 8088's way of doing things. So to access 16megs of memory,
the 80286 created Selectors that pointed to memory. A selector has a
starting point and a size, and access rights to determine if the CPU
can read, write, or execute the memory. Since we used selectors that
was created in memory and the segment registers just pointed to which
selector we wanted to use, we could now use more than 16 bits to store
the memory location. This allowed the 80286 to access all 16 megs of
memory it could handle. This was good, but along came the 80386,
which made a lot of things WAY easier for programmers. Better
instructions, access to 4 Gigabytes of memory, better memory
handling/virtual memory access, etc. Along with access to more memory
a Virtual'86 mode was also created if I'm not mistaken... This was an
interesting mode.... With it, the CPU could be in protected mode, but
somehow DOS programs could run in real mode, while protected mode apps
run in protected mode, but the DOS apps are still under some protected
mode rules.... You can't go messing around with every single CPU
instruction in Virtual 86 mode... Alot of the CPU detection
instructions won't work in Virtual'86 mode... O.k. I left a lot out,
but it hopefully gives you a brief idea of what is meant by
real/protected/v86 mode....

John H. Guillory

unread,
Jan 25, 2004, 7:05:02 PM1/25/04
to
On Sun, 25 Jan 2004 12:31:57 +0100, Herbert Kleebauer <kl...@unibwm.de>
wrote:

>> Should all new drivers start out with a Model-T, too?
>
>I didn't speak of an ancient 8086 processor. Even the newest x86 processor
>supports the three modes: real/V86/protected mode. And you can use the
>32 bit instructions and all the 32 bit addressing modes in any of this

What about the fact that CPU its self BOOTS up in REAL mode.... I mean
Gee, if you have the illusion that your going to start off programming
your own OS (as every beginner at ASM seems to have) completly in
assembly language, then it'd seem you'd WANT to learn real mode
first.... Since after all, you'll need to know enough about it to get
your butt in protected mode....

Charles A. Crayne

unread,
Jan 25, 2004, 7:15:20 PM1/25/04
to
On Mon, 26 Jan 2004 00:05:02 +0000 (UTC)
"John H. Guillory" <jj...@remoooooovethisdrizzle.com> wrote:

:What about the fact that CPU its self BOOTS up in REAL mode.... I mean


:Gee, if you have the illusion that your going to start off programming
:your own OS (as every beginner at ASM seems to have) completly in
:assembly language, then it'd seem you'd WANT to learn real mode
:first.... Since after all, you'll need to know enough about it to get
:your butt in protected mode....

It's been a long time since I wrote code to switch from real to protected
mode, and my memory of it grows dim, but I'm fairly certain that I didn't
need any int 21h calls to do so. :-)

Matt Taylor

unread,
Jan 25, 2004, 10:17:05 PM1/25/04
to
"Herbert Kleebauer" <kl...@unibwm.de> wrote in message
news:4013A92D...@unibwm.de...

> August Derleth wrote:
> > Herbert Kleebauer wrote:
>
> > > But even if an Intel 32 bit processor is used, a beginner always
> > > should start learning assembly programming in real or V86 mode and
> > > not in protected mode.
> >
> > Should all new drivers start out with a Model-T, too?
>
> I didn't speak of an ancient 8086 processor. Even the newest x86 processor
> supports the three modes: real/V86/protected mode. And you can use the
> 32 bit instructions and all the 32 bit addressing modes in any of this
> three modes. So it doesn't matter at all which of this modes you use to
> LEARN assembly programing. But it is important to use an operating
> system with a simple interface so you can concentrate on the language
> of the processor and don't have to spend much more time with the OS
> interface than with the processor instructions. And the int21
> interface is much easier to use (and still supported in the newest
> MS operating systems for V86 mode) than the Win32 interface.
<snip>

No, this is simply not true. Whether I put the data in registers or push it
to the stack, there is no difference in complexity. Calling functions with
actual names rather than some coded numbers is much easier to remember, so
if I were to make a case for either calling convention I would say that
Linux/Win32 is easier than DOS.

Here are 2 pieces of code, one for DOS and the other for Win32:

; DOS code
mov ah, 1
int 0x21 ; read a character from stdin with echo

mov ax, 0x4C00
int 0x21 ; exit to DOS

; Win32 code
call getch

push 0
call exit

So what exactly are your metrics for easiness? Shorter code? Here the Win32
code is shorter by 1 instruction. The gets() and puts() functions are only
slightly trickier since one must pass a pointer to __iob.

<snip>


> We are speaking about LEARNING assembly programming and for that
> purpose 64k are enough. It is a different thing if you want to
> write real applications in assembler. But in order to write
> applications in assembler you first have to learn assembly programing
> which is much easier if you use v86 mode. Besides, nobody will write
> applications in assembler any more (that is much more obsolete than
> a 8086 processor). Use a HLL and if necessary an inline assembler or
> link to small piece of code written in assembler.

So why bother with learning 16-bit at all if you're not going to use it?
Teach the novice to do inline assembly and tackle real problems. I cannot
count the number of times someone has asked (either here or elsewhere) why
they can't use interrupts to make DOS calls from Windows. Then there are
endless questions about segmentation. You've pointed out that 32-bit
addressing can be used in v8086 or real-mode, but none of the tutorials
mention this! The novice is always directed to use convoluted 16-bit
addressing modes. Even with 32-bit addressing modes there are still caveats
for the 16-bit programmer.

The main Win32 question I hear is, "Why does my program crash?" where the
crash stems from incorrect calling conventions or from calling a DLL
function directly. These questions are much more easily answered. Also, they
are completely avoided by using the C runtime functions and statically
linking to them.

> > > As an example a simple program which reads from stdin and writes
> > > to stdout, converting all upper case characters to lower case.
> > > To make it compatible with the win32 version, it uses mostly
> > > 32 bit instructions. But even then the generated executable
> > > file size is only 109 bytes.
> >
> > Executable size? Dick-waving nonsense. Blocks on a hard drive are larger
> > than that. You gain nothing by stripping the binary to less than one or
> > two Kibibytes.
>
> You are right, it doesn't matter how much disc space is needed for
> a program. But we are speaking about learning assembly programming.
> And it does matter if a beginner has to understand 1000 or only 100
> bytes to successfully run his first assembler program.

<snip>

Number of instructions is more important, and as I've been saying, most C
runtime functions have nearly a 1:1 correspondance with DOS system
functions. It is also easier for a person to remember names than it is to
remember numbers. Beside that, a lot of assembly programmers come from C/C++
experience. It is far simpler for the novice who has already learned his
native tools to continue using them.

-Matt


Matt Taylor

unread,
Jan 25, 2004, 10:38:28 PM1/25/04
to
"Matt Taylor" <pa...@tampabay.rr.com> wrote in message
news:Vu%Qb.111831$873.1...@twister.tampabay.rr.com...
<snip>

> So what exactly are your metrics for easiness? Shorter code? Here the
Win32
> code is shorter by 1 instruction. The gets() and puts() functions are only
> slightly trickier since one must pass a pointer to __iob.
<snip>

Now I get to correct myself. I was thinking of fgets() and fputs(). The
gets() and puts() functions assume stdin, so they are just as simple as DOS
system calls on both Win32 and Linux.

-Matt


Tim Roberts

unread,
Jan 25, 2004, 11:58:36 PM1/25/04
to
August Derleth <s...@sig.now> wrote:

>Herbert Kleebauer wrote:
>>
>> There are still much more 4/8 bit processors sold than 16/32/64 processors.
>
>I'd like a citation for this claim. Are seriously tiny embedded systems
>truly that common?

Does it really seem that surprising? Virtually every appliance with a
power supply has a microprocessor in it, and only a small fraction of them
need anything more powerful than a PIC or 8051. Rest assured that NO
equipment maker is going to pay for a single bit of processor more than
they need. The ABS on your car probably uses an 8-bit processor. Your
microwave almost certainly does. Your telephone does. Your refrigerator
and washing machine probably do.

Those applications completely dwarf applications for 32-bit processors.
--
- Tim Roberts, ti...@probo.com
Providenza & Boekelheide, Inc.

Bjarni Juliusson

unread,
Jan 26, 2004, 12:26:41 AM1/26/04
to
I'm in the mood for a little nitpicking.

> Intel started long ago with the 4040, which was used only in

They started with the world's first microprocessor, the 4004, in 1971.
Development had started in 1969. It was a 4 bit chip. In 1972 Intel
introduced the 8 bit 8008.

> calculators. Later, the 8080 was designed and used in CP/M based

Correct. This was in 1974. The 8080 was an 8 bit processor with 16 bit
addresses, and it was the model for the incredibly popular Z80.

> systems, then came along the 8088 (and soon after 8086), which was
> used on PC's, XT's, and clones. These systems used 16-bit
> instructions on what was an 8-bit CPU (or in the case of the 8086 a
> 16-bit cpu with an 8-bit bus), and in order to access more memory than

Very common mistake. The 8086 was released in 1978, and it is a true 16
bit processor. To allow for cheaper circuit boards, Intel released the
8088 in 1979. This is an exact copy of the 8086, but with an 8 bit
external data bus. It is a 16 bit processor inside, just like the 8086.

> possible with a single 16-bit register, Intel used segment:offset
> scheme of doing things. The segment was shifted 4 bits and added to
> the offset to point to the actual memory location. This meant that
> any given memory location could be referenced in several different
> ways, eg.

Now this is all true. Then came the 80286 with 16 bit protected mode,
then the 80386 with 32 bit protected mode, and the rest have essentially
been fast 386s.


--
Remove the furry animal from my address to send email:

bjarni...@update.ferret.uu.se

August Derleth

unread,
Jan 26, 2004, 1:37:14 AM1/26/04
to
Tim Roberts wrote:

> August Derleth <s...@sig.now> wrote:
>
>
>>Herbert Kleebauer wrote:
>>
>>>There are still much more 4/8 bit processors sold than 16/32/64 processors.
>>
>>I'd like a citation for this claim. Are seriously tiny embedded systems
>>truly that common?
>
>
> Does it really seem that surprising? Virtually every appliance with a
> power supply has a microprocessor in it, and only a small fraction of them
> need anything more powerful than a PIC or 8051. Rest assured that NO
> equipment maker is going to pay for a single bit of processor more than
> they need. The ABS on your car probably uses an 8-bit processor. Your
> microwave almost certainly does. Your telephone does. Your refrigerator
> and washing machine probably do.

I simply didn't realize those little things would have general-purpose
programmable logic in them, as opposed to special-purpose circuitry and
various amounts of ROM. I know the era of the electromechanical system
is over, but has everyone moved from the simple special-purpose chips to
the more complex 8051s and such?

Bx.C

unread,
Jan 26, 2004, 1:37:35 AM1/26/04
to

"Bjarni Juliusson" <bjarni...@update.ferret.uu.se> wrote in message
news:N21Rb.79971$dP1.2...@newsc.telia.net...

hehe... yah... my A+ instructor told us just the other day that a 586 is
simply two 486's put together in one package.... (what i think he was
actually trying to explain at the time, was the fact that the 586 had two
instruction pipelines.... but he didn't do a very good job.... looking
around the room, he left the other students more confused than before)...


Herbert Kleebauer

unread,
Jan 26, 2004, 6:26:01 AM1/26/04
to
Matt Taylor wrote:
> "Herbert Kleebauer" <kl...@unibwm.de> wrote in message

> No, this is simply not true. Whether I put the data in registers or push it
> to the stack, there is no difference in complexity. Calling functions with
> actual names rather than some coded numbers is much easier to remember, so
> if I were to make a case for either calling convention I would say that
> Linux/Win32 is easier than DOS.
>
> Here are 2 pieces of code, one for DOS and the other for Win32:
>
> ; DOS code
> mov ah, 1
> int 0x21 ; read a character from stdin with echo
>
> mov ax, 0x4C00
> int 0x21 ; exit to DOS

This are four processor instructions and the generated executable
contains 9 bytes: B4 01 CD 21 B8 00 4C CD 21
This is easy to understand for any beginner.


> ; Win32 code
> call getch
>
> push 0
> call exit

And that is a joke? That's why beginner learning assembly
programming in win32 think, INVOKE is a processor instruction
and exit is some function stored in the CPU, because you can
call it without providing it.

Now let's look what an assembly programmer has to learn
to end a program by calling ExitProcess.


6a 00 moveq.l #0,-(sp)
ff 15 00401008 jsr.l (ExitProcess)

You only need 2 instructions. The first is a simple push (no
problem to understand), but the second is an indirect call to
a subroutine. In order to execute this call you have to provide
a memory location where this address is stored:

ExitProcess: dc.l AddressOfExitSubroutine

But where to get this "AddressOfExitSubroutine"? You have to
ask the loader to insert this address at the location
"ExitProcess" at load time. In order to do this, you have to
specify at a predefined location in the exe file a pointer to
and the length of two tables:

dc.l imp_start,imp_size ; Import Directory
dc.l iat_start,iat_size ; Import Address Table

In the Import Address Table are all the memory locations
where the subroutine addresses are stored:

iat_start=@-ImageBase


KERNEL32_thunk:
ExitProcess:: dc.l KERNEL32_ExitProcess -ImageBase

dc.l 0
iat_size=@-ImageBase-iat_start


In the Import Directory you have to make an entry for
any DLL imported:

imp_start==@-ImageBase
imp:

dc.l KERNEL32_import -ImageBase
dc.l 0
dc.l 0
dc.l KERNEL32_name -ImageBase
dc.l KERNEL32_thunk -ImageBase

dc.l 0
dc.l 0
dc.l 0
dc.l 0
dc.l 0

imp_size==@-imp


Beside the pointer to the Import Address Table there a three other
pointers to data which you have also to supply:

KERNEL32_name:
dc.b 'KERNEL32.dll',0
even

KERNEL32_import:
dc.l KERNEL32_ExitProcess -ImageBase
dc.l 0
even

KERNEL32_ExitProcess:
dc.w 0
dc.b 'ExitProcess',0
even


All this data structures a beginner has to supply and to understand
before he can exit his program. Now compare this with with the 5 bytes
in the "DOS" version. And don't tell me, an assembly programmer doesn't
have to know this. Otherwise it is just a HLL with an inline assembler
where you write a part of the program using processor instructions
and the rest is generated by the compiler/"High Level Assembler".


> So what exactly are your metrics for easiness? Shorter code? Here the Win32
> code is shorter by 1 instruction. The gets() and puts() functions are only
> slightly trickier since one must pass a pointer to __iob.

Now just recount.


> You've pointed out that 32-bit
> addressing can be used in v8086 or real-mode, but none of the tutorials
> mention this!

Sorry, but there is only one documentation for learning assembly
programming and that is the processor manual and there you will
find all information about the available addressing modes.


> The main Win32 question I hear is, "Why does my program crash?" where the
> crash stems from incorrect calling conventions or from calling a DLL
> function directly. These questions are much more easily answered. Also, they
> are completely avoided by using the C runtime functions and statically
> linking to them.

That is not assembly programming, that is the generation of a
sequence of operating system / library calls. Look at the simple
task to draw a circle on the screen. In "DOS" mode you make an
int10 to switch to graphics mode and then you can concentrate
on writing the circle function in assembler. The output
to screen is a simple move instruction. Now compare this with
the overhead in Windows to set a single pixel on the screen.
But if you have managed this, you don't need to worry about the
assembler code for the circle, simple call some draw_circle
function in a graphics library. That has nothing to do with
assembly programming.

Randall Hyde

unread,
Jan 26, 2004, 8:13:48 AM1/26/04
to

"August Derleth" <s...@sig.now> wrote in message
news:IF1Rb.10471$dF4....@fe02.usenetserver.com...

> Tim Roberts wrote:
>
>
> I simply didn't realize those little things would have general-purpose
> programmable logic in them, as opposed to special-purpose circuitry and
> various amounts of ROM. I know the era of the electromechanical system
> is over, but has everyone moved from the simple special-purpose chips to
> the more complex 8051s and such?
>
Yes. It's much cheaper to use one of these devices in most cases.
Not the mention the fact that it has probably been at least a decade
since any school has really taught students how to design anything
without using microprocessors :-)
Cheers,
Randy Hyde


Matt Taylor

unread,
Jan 26, 2004, 8:35:35 AM1/26/04
to
"Herbert Kleebauer" <kl...@unibwm.de> wrote in message
news:4014F949...@unibwm.de...

> Matt Taylor wrote:
> > "Herbert Kleebauer" <kl...@unibwm.de> wrote in message
>
>
> > No, this is simply not true. Whether I put the data in registers or push
it
> > to the stack, there is no difference in complexity. Calling functions
with
> > actual names rather than some coded numbers is much easier to remember,
so
> > if I were to make a case for either calling convention I would say that
> > Linux/Win32 is easier than DOS.
> >
> > Here are 2 pieces of code, one for DOS and the other for Win32:
> >
> > ; DOS code
> > mov ah, 1
> > int 0x21 ; read a character from stdin with echo
> >
> > mov ax, 0x4C00
> > int 0x21 ; exit to DOS
>
> This are four processor instructions and the generated executable
> contains 9 bytes: B4 01 CD 21 B8 00 4C CD 21
> This is easy to understand for any beginner.

As has been pointed out several times already, the length of instructions is
completely and totally irrelevant. We are talking about learning assembly,
right?

> > ; Win32 code
> > call getch
> >
> > push 0
> > call exit
>
> And that is a joke? That's why beginner learning assembly
> programming in win32 think, INVOKE is a processor instruction
> and exit is some function stored in the CPU, because you can
> call it without providing it.

I've never heard of anyone thinking this. If someone does not understand the
concept of libraries, they have a lot more to learn than just assembly
language. Personally, I understood what a library was before I even knew
what assembly language was.

Yes, it is possible to use invoke which makes life even simpler for the
Win32 programmer. I prefer not to use it, but that is another discussion
entirely. For this discussion, my example did not include invoke.

> Now let's look what an assembly programmer has to learn
> to end a program by calling ExitProcess.
>
>
> 6a 00 moveq.l #0,-(sp)
> ff 15 00401008 jsr.l (ExitProcess)
>
> You only need 2 instructions. The first is a simple push (no
> problem to understand), but the second is an indirect call to
> a subroutine. In order to execute this call you have to provide
> a memory location where this address is stored:
>
> ExitProcess: dc.l AddressOfExitSubroutine

<snip>

Since when? That is automatically provided to you unless you hexedit your
own executable. I thought we were talking about learning assembly language,
not writing demos. Besides the fact that one can call exit() instead, it is
still simpler to explain the difference between an indirect/direct call than
it is to explain segmentation. As I said before, most people I've met who
pick up assembly do so *after* learning C. Since C has an analogue for this,
it is quite easy to explain.

> All this data structures a beginner has to supply and to understand
> before he can exit his program. Now compare this with with the 5 bytes
> in the "DOS" version. And don't tell me, an assembly programmer doesn't
> have to know this. Otherwise it is just a HLL with an inline assembler
> where you write a part of the program using processor instructions
> and the rest is generated by the compiler/"High Level Assembler".

<snip>

Utter nonsense. I've never constructed a PE header by hand, and I don't
intend to do that ever. It's a great exercise in futility. All of the tools
I've worked with will build the IAT and related structures automatically.
Nasm will allow me to build my own, but that's a complete waste of time.

Here's the equivalent of B8 00 4C CD 21 using ExitProcess:

bits 32

section .text
extern _ExitProcess@4

_main:
push 0
call [_ExitProcess@4]

> > You've pointed out that 32-bit
> > addressing can be used in v8086 or real-mode, but none of the tutorials
> > mention this!
>
> Sorry, but there is only one documentation for learning assembly
> programming and that is the processor manual and there you will
> find all information about the available addressing modes.

Also nonsense. There are a number of tutorials on assembly which take
information from Intel manuals and organize it for the novice. AoA comes
foremost to mind. Personally, I read the 8086 & 80386 manuals, and I thought
they were well-written. Unfortunately newer manuals have too much
information as x86 has exponentially increased in complexity. Most of that
information is for people writing operating systems and is completely
meaningless to the novice.

> > The main Win32 question I hear is, "Why does my program crash?" where
the
> > crash stems from incorrect calling conventions or from calling a DLL
> > function directly. These questions are much more easily answered. Also,
they
> > are completely avoided by using the C runtime functions and statically
> > linking to them.
>
> That is not assembly programming, that is the generation of a
> sequence of operating system / library calls. Look at the simple
> task to draw a circle on the screen. In "DOS" mode you make an
> int10 to switch to graphics mode and then you can concentrate
> on writing the circle function in assembler. The output
> to screen is a simple move instruction. Now compare this with
> the overhead in Windows to set a single pixel on the screen.

<snip>

Yes, and in 320x200 unless you care to explain segmentation, banked modes,
color planes, and other concepts to the novice. At least use DPMI with VESA
2. DirectDraw isn't ideal, but at least one can create a framework and then
forget about it.

Besides, what does that have to do with learning assembly? Surely you don't
think that the demoscene is the *only* reason people learn assembly.

-Matt


C

unread,
Jan 26, 2004, 9:45:02 AM1/26/04
to
"Bx.C" <nu...@the.void> wrote in message news:<5_1Rb.37873$DX.2...@bignews3.bellsouth.net>...

>
> hehe... yah... my A+ instructor told us just the other day that a 586 is
> simply two 486's put together in one package.... (what i think he was
> actually trying to explain at the time, was the fact that the 586 had two
> instruction pipelines.... but he didn't do a very good job.... looking
> around the room, he left the other students more confused than before)...

:-)

That would be a more accurate description of IBMs multicore Power
series, or possibly Intels latest "HyperThreading" technology,
than superscalar processing as applied to the 586.

Oh, and by the way the 486 was pipelined. Ie. it decodes the
instruction in stages allowing it to overlay the decoding
of instructions -- which is why most instructions have a throughput
of only 1 clock, even though they take several cycles to process.
A basic pipe line would look something like...

Fetch -- Decode -- Fetch Operands -- Execute -- Write Back

An seperate instruction can be being processed at each stage,
ie. for the above pipeline, up to 5 instructions can be being
processed simultaneously, prodided there are no conflicts.
Conflicts, such as AGI stalls, cause pipeline bubbles.

The 586 (Pentium) was superscalar. Ie. it can execute two
instructions simultaneously (provided they did not conflict
by needing each others resources), this is achieved by having
two pipelines and some nifty logic detect conflicts.

Later processors (686+) are 3-way superscalar 'out-of-order'.
Ie. they can have 3 pipelines and can execute instructions in
a different order to that which the programmer specifies.

I hope this has undone some of the confusion/damage your
instructor inflicted. Of course, I have attempted to explain
in a few paragraphs what would normally take several chapters,
therefore many details have been elided. To fill in the many
gaps I suggest you have a look at the book "Hennessy, J., and
Patterson, D. Computer Architecture - A Quantitive Approach.
Morgan Kaufmann Publishers Inc., 1990". Though it is getting
a little old, it is still the definitive text on the subject.
(I think a second edition was published around 1996.)

C
2004-01-25

Robert Wessel

unread,
Jan 26, 2004, 5:47:49 PM1/26/04
to
August Derleth <s...@sig.now> wrote in message news:<IF1Rb.10471$dF4....@fe02.usenetserver.com>...
> I simply didn't realize those little things would have general-purpose
> programmable logic in them, as opposed to special-purpose circuitry and
> various amounts of ROM. I know the era of the electromechanical system
> is over, but has everyone moved from the simple special-purpose chips to
> the more complex 8051s and such?


The embedded controller market is something like seven billion units
per year. CPUs intended for the primary computing market ship
something on the order of 150 million units/year. Also, many of the
controller cores ship embedded in a chip providing application
specific functionality.

It's hard to beat the cost (or flexibility) of small microcontrollers.
Under a couple of bucks each for a few thousands units gets you a
single chip with RAM, ROM, CPU, and an assortment of interfaces (say
something 8051ish, with 8KB of ROM, a few hundred bytes of RAM, a
couple of dozen I/O pins). Hard to put much discrete logic on a board
for a couple of bucks. Of course you can spend considerably more (and
get much more).

Dragon Lord

unread,
Jan 26, 2004, 9:04:33 PM1/26/04
to

"Beth" <BethS...@hotmail.NOSPICEDHAM.com> wrote in message
news:YICQb.244$bn3...@newsfep3-gui.server.ntli.net...

>
> High-level functions:
> INT 21h, AH = 09h: Print String
> INT 21h, AH = 0Ah: Buffered Keyboard Input (with echo)
>
> [ These functions deal with complete strings under DOS's control; Easy
> to use but can't be "customised" much so you have to accept however
> DOS deals with the user I/O... ]
>
> Low-level functions:
> INT 21h, AH = 01h: Keyboard Input with Echo
> INT 21h, AH = 02h: Display Output
>
>

Your also forgetting

INT 21h, AH = 3Fh
INT 21h, AH = 40h

3F = Read
40 = Write

setting BX
0 = stdin
1 = stdout
2 = stderr

and in fact, MSDOS version past 2, 09 and 01 called 3Fh and 0A and 02
called 40, so calling 3F and 40 is actually faster than 09 0A 01 02.
Although, you would have to do your own echoing.

Jeremy

Beth

unread,
Jan 27, 2004, 1:52:31 AM1/27/04
to
Dragon Lord wrote:

> Beth wrote:
> >
> > High-level functions:
> > INT 21h, AH = 09h: Print String
> > INT 21h, AH = 0Ah: Buffered Keyboard Input (with echo)
> >
> > [ These functions deal with complete strings under DOS's control;
Easy
> > to use but can't be "customised" much so you have to accept
however
> > DOS deals with the user I/O... ]
> >
> > Low-level functions:
> > INT 21h, AH = 01h: Keyboard Input with Echo
> > INT 21h, AH = 02h: Display Output
>
> Your also forgetting
>
> INT 21h, AH = 3Fh
> INT 21h, AH = 40h
>
> 3F = Read
> 40 = Write
>
> setting BX
> 0 = stdin
> 1 = stdout
> 2 = stderr

As the question was just "I/O" in general, not necessarily screen
output or keyboard input, then I've "forgotten" an awful lot:

INT 21h, AH = 03h: READ CHARACTER FROM STDAUX
INT 21h, AH = 04h: WRITE CHARACTER TO STDAUX
INT 21h, AH = 05h: WRITE CHARACTER TO PRINTER
INT 21h, AH = 06h: DIRECT CONSOLE I/O
INT 21h, AH = 07h: DIRECT CHARACTER INPUT, WITHOUT ECHO
INT 21h, AH = 08h: CHARACTER INPUT WITHOUT ECHO
INT 21h, AH = 0Ch: FLUSH BUFFER AND READ STANDARD INPUT

....for starters, which actually contains some more console-style
I/O...but why stop there, when there's also:

INT 21h, AH = 0Fh: OPEN FILE USING FCB
INT 21h, AH = 10h: CLOSE FILE USING FCB
INT 21h, AH = 11h: FIND FIRST MATCHING FILE USING FCB
INT 21h, AH = 12h: FIND NEXT MATCHING FILE USING FCB
INT 21h, AH = 13h: DELETE FILE USING FCB
INT 21h, AH = 14h: SEQUENTIAL READ FROM FCB FILE
INT 21h, AH = 15h: SEQUENTIAL WRITE TO FCB FILE
INT 21h, AH = 16h: CREATE OR TRUNCATE FILE USING FCB
INT 21h, AH = 17h: RENAME FILE USING FCB
INT 21h, AH = 21h: READ RANDOM RECORD FROM FCB FILE
INT 21h, AH = 22h: WRITE RANDOM RECORD TO FCB FILE
INT 21h, AH = 23h: GET FILE SIZE FOR FCB
INT 21h, AH = 24h: SET RANDOM RECORD NUMBER FOR FCB
INT 21h, AH = 25h: SET INTERRUPT VECTOR
INT 21h, AH = 27h: RANDOM BLOCK READ FROM FCB FILE
INT 21h, AH = 28h: RANDOM BLOCK WRITE TO FCB FILE
INT 21h, AH = 2Ch: GET SYSTEM TIME
INT 21h, AH = 2Dh: SET SYSTEM TIME

....blah-blah-blah...?

Arguably, in fact, practically _every single MS-DOS interrupt_ could
be considered as being some type of "I/O" in one way or another...such
as even "Get System Time" and "Set System Time", at the end of the
list above, are effectively doing "I/O" with the system's time
(reading / writing to it)...

Let me throw you a clue: I, perhaps, was not being exhaustive of every
single DOS interrupt and its complete internal workings (with all the
details and at least one example for all of DOS from top to bottom,
don't expect such a post to appear before 2009 for the length of what
it would be...and you'd probably need to upgrade your hard drive
simply to accomodate the "Library of Congress" it would likely
represent)...

No, what I was doing was trying to "go deep" (in a newbie-relative
way, I'd stress...it won't seem at all "deep" to most out there ;) on
a few selected DOS interrupts to show how they might be used, rather
than "go broad" by throwing up a listing of DOS interrupts (which,
after all, can be got from an awful lot of sources :) and then say
"work it out for yourselves!!!"...

It was intended as a practical way to _get into_ using DOS
interrupts...some actual examples of how they would be used in a
program to get a particular effect...and so on and so forth...that's
what a "newbie" needs at first...of course, once they get the basic
pattern and idea of how it works, then, sure, throw up some list of
all available DOS interrupts and they'll know how it all roughly works
to pick and choose the ones they want...and so on and so
forth...indeed, _after_ reading my post to set the basic pattern and
usage of these things, _then_ your information might, indeed, be
exactly what the newbie wants to know about...

Getting the idea yet? I did not "forget" that there were other DOS
"I/O" interrupts at all...it was simply just never my intention to
cover all of them in a single post...I selected those four as
"representative", as a symmetrical "two sets of two": one is input,
the other output and then each pair is either "low-level" or
"high-level"...because that shows both basic operations in a "let DOS
do it!" way and then showing how you can also take a more "low-level"
interrupt and use your own code to "flesh it out" (and the ability
this provides you to "customise" your "I/O" a little :)...

> and in fact, MSDOS version past 2, 09 and 01 called 3Fh and 0A
and 02
> called 40, so calling 3F and 40 is actually faster than 09 0A 01 02.
> Although, you would have to do your own echoing.

No doubt; But when writing your first "Hello, world!"-like programs
and getting to grips with how to call DOS interrupts in the first
place - perhaps also, likely at this stage, how to get your assembler
itself working to assemble things - do we care about "fastest"? How
does this information help the newbie at a stage of _not even really
being sure whether "printf" is a machine instruction or not_?

I can see it now: "Good morning, children! Today, our kindergarten
class - after you've drunk your milk and we've dealt with little
Johnny's "accident" - will be counting blocks, colouring in pictures
with crayons...and then posing the ultimate questions of the universe
by conducting high dangerous experiments on elementary particles in a
particle accelerator to probe the nature of Uncertainty Theory, in
order to consider the philosophical and psychological ramifications of
it with respect to the various cosmological models that could wholly
conform to said observations...and, if we've got time after that, we
can sing that song where you all have to do the special hand
actions...won't this be fun, children?" ;)

I have a little rhyme about this, you might want to learn:

"From what you were to what you will become...
You must _learn to walk_ before you can run!"

[ There are also "hand actions" you can do that go along with
it...but, well, one thing at a time, yes? ;) ]

Nevertheless, your information here is valid, interesting and
potentially useful...it's just, well, "Woah, horsey! Woah!"...

Beth :)


Beth

unread,
Jan 27, 2004, 2:37:17 AM1/27/04
to
August Derleth wrote:
> I notice you /aren't even using 8088 opcodes/. Post-increment
indexing
> modes? I guess it's the 68000, if it's a microprocessor, but it
could
> (possibly) be a PDP or a VAX.
>
> I'm aware that this was cross-posted to alt.lang.asm. But why would
you
> hype V86 and other Intel things if your code wasn't even going to be
for
> Intel chips?

Just for clarification, Herbert's got some very weird habits and
opinions...of which, you've just met one of the weirdest...

Herbert has written himself an x86 assembler which uses
Motorola-inspired syntax...yes, the code you were looking at there
_IS_ x86 code...but he's changed around the syntax to make it look
like 68K code...for example, something like "trap #$21" would be "int
21h" in the more conventional Intel syntax...

[ And, with priceless irony, Herbert has been known to complain about
HLA..._because_ of its "non-standard" syntax!! Three words come to
mind: "pot", "kettle" and "black"...it's quite ludicrous,
really...Randy just adds brackets and swaps the operands around in a
few cases and this is apparently so "non-standard" as to be "the evil
spawn of satan" or something...yet, using syntax from a completely
different architecture altogether - the 68K series, which has
_fundamental differences_ like endianness and "data / address"
registers and so forth - is completely okay and not in the slightest
bit confusing for Herbert to be posting to x86 forums!! ]

Don't worry too much about Herbert's opinions, as they all seem to
boil down to: "If you're not programming your code using a soldering
iron and oscillascope against the bare metal of the motherboard
itself, then you're not really programming at all!"...for example, he
creates all his Windows PE files manually by using "DB" to define all
the headers because the use of a linker is probably some "evil spawn
of satan" thing in his own mind...

You were on the money, August, with that "dick waving" machismo
comment...I mean, he may claim that his 68K-inspired syntax is all
about "Motorola have a cleaner syntax" but, in the end, we _ALL KNOW_
that it's really a case of: "Look how hard I am! I can use totally
confusing syntax! I know more than one assembly language, as you can
see, so I'm a really hard guru-type person!"...and all that kind of
nonsense...thus, his opinions as to what is best for a beginner to use
are, as you've rightly pointed out, hardly things to take all that
seriously: "beginners should eat steel nails and pour raw coffee down
their throats or they are just wimps!! And there's only room for 'hard
men' in assembly programming!!" ;)

Beth :)


Beth

unread,
Jan 27, 2004, 2:55:24 AM1/27/04
to
Matt Taylor wrote:
> Since when? That is automatically provided to you unless you hexedit
your
> own executable.

Exactly; Herbert _DOES_ hexedit his own PE executable files (using a
68K-inspired syntax, even though it's on an x86, even!)...

He insists that you're not doing "real assembly" (whatever that
implies) unless you "DB" all your headers manually...of course, what
knowing the format of the OS-specific Microsoft PE file format has got
to do with comprehending the workings of an x86 chip, goodness
knows...but this is Herbert's logic and, apparently, beginners aren't
learning anything at all and aren't "real" macho coders (and if you're
not a "macho coder" like Herbert then you aren't even a blip on his
radar, as far as he's concerned), unless they also follow this often
rather bizarre logic he has...

Beth :)


Herbert Kleebauer

unread,
Jan 27, 2004, 11:55:42 AM1/27/04
to
Beth wrote:

> Don't worry too much about Herbert's opinions, as they all seem to
> boil down to: "If you're not programming your code using a soldering
> iron and oscillascope against the bare metal of the motherboard
> itself, then you're not really programming at all!"...for example, he
> creates all his Windows PE files manually by using "DB" to define all
> the headers because the use of a linker is probably some "evil spawn
> of satan" thing in his own mind...

Beth, you still didn't get the point. We are talking about
learning assembly programming and not about writing applications
in assembler (nearly nobody does this in these days). Pupils
still learn to add/sub/mul/div using their brain and a pencil
even if they later only use a pocket calculator. They learn to
write with a pencil and to spell words and later only use a
keyboard and a spell checker. If you learn a trade, you still
have to learn how things are done manually even though later you
will never do this again because it is done by a machine.

And the same is true for learning assembly programming.
You should do all things at the lowest level to understand
what happens. Once you have understood it, you don't need to
do it again, use a compiler/linker and libraries to do the
work for you.


PS: Did you ever see the bootstrap code of a PDP11/45 realized
with a diode matrix on a PCB. That's "programming your code
using a soldering iron".

Bx.C

unread,
Jan 27, 2004, 12:12:21 PM1/27/04
to

"C" <black...@asean-mail.com> wrote in message
news:33d97ee5.04012...@posting.google.com...

yes, but i must say... i seriously doubt the rest of my A+ class are ready
for this info..... i tried having a logical technical discussion about the
relevance of Microsoft DOS in current and future operating systems (while
keeping in mind that v86 sessions won't run in Long mode on 64-bit
processors).... and while i myself debated both ways... that Microsoft would
keep some form of DOS, even while running under the most secure modes of
later processors, but may re-work it to be a simple 32-bit command line
interface run under protected mode only, leaving out the possibility for
switching between v86 sessions and 64-bit mode... which would be a very
nasty job to keep track of, trying to jump back and forth constantly... (and
yet, they may keep the current real mode or v86 mode compatible DOS simply
for pre-winboot tasks.... disk maintenance... registry repair... password
recovery... etc) ..... the person i was sitting with, discussing this
with... seemed lost in the first few minutes...

and right now.... looking back... i think i had too much coffee this
morning...


Dragon Lord

unread,
Jan 27, 2004, 4:10:52 PM1/27/04
to
Having more resources isn't bad. Not only that, these interrupts would be
more understandable come from say... a unix platform, or C++ background.
cin, cout, cerr can be simulated this way. Also, explaining to users the
different approaches, allows the user to decide which is best for the
situation in which they are writing it for. You make it sound even bad to
come up with alternatives. Also, I don't think the console channels end up
in FCB, so 0F-17 and 21-28. But as I was just showing SOME alternatives,
you could also use IN and OUT to get your data if your really daring.

August Derleth

unread,
Jan 27, 2004, 6:47:30 PM1/27/04
to
Beth wrote:
> August Derleth wrote:
>
>>I notice you /aren't even using 8088 opcodes/. Post-increment
>
> indexing
>
>>modes? I guess it's the 68000, if it's a microprocessor, but it
>
> could
>
>>(possibly) be a PDP or a VAX.
>>
>>I'm aware that this was cross-posted to alt.lang.asm. But why would
>
> you
>
>>hype V86 and other Intel things if your code wasn't even going to be
>
> for
>
>>Intel chips?
>
> Herbert has written himself an x86 assembler which uses
> Motorola-inspired syntax...yes, the code you were looking at there
> _IS_ x86 code...but he's changed around the syntax to make it look
> like 68K code...for example, something like "trap #$21" would be "int
> 21h" in the more conventional Intel syntax...

Oh, ok. It is just him. I was wondering who would make and market an x86
assembler with 68000 syntax, and who would be bizarre enough to
buy/download it. Knowing it's a homebrew makes more sense, in that I
only have to posit /one/ weirdo to make it happen. ;)

>
> [ And, with priceless irony, Herbert has been known to complain about
> HLA..._because_ of its "non-standard" syntax!! Three words come to
> mind: "pot", "kettle" and "black"...it's quite ludicrous,
> really...Randy just adds brackets and swaps the operands around in a
> few cases and this is apparently so "non-standard" as to be "the evil
> spawn of satan" or something...yet, using syntax from a completely
> different architecture altogether - the 68K series, which has
> _fundamental differences_ like endianness and "data / address"
> registers and so forth - is completely okay and not in the slightest
> bit confusing for Herbert to be posting to x86 forums!! ]

HLA's syntax isn't something I particularly enjoy, but it's a sight more
readable to the casual reader than Herbert's code. (I'm a
dyed-in-the-wool nasm lover, and so I disagree with Randy on a few
issues related to what an assembler should be expected to do, which goes
quite a bit deeper than syntax. But at least we both agree on what the
int opcode should be called. :) )

>
> Don't worry too much about Herbert's opinions, as they all seem to
> boil down to: "If you're not programming your code using a soldering
> iron and oscillascope against the bare metal of the motherboard
> itself, then you're not really programming at all!"...for example, he
> creates all his Windows PE files manually by using "DB" to define all
> the headers because the use of a linker is probably some "evil spawn
> of satan" thing in his own mind...

Yeah. I was wondering just what made his 32-bit examples so damned huge.
I didn't take the time to realize the yahoo was /writing his own headers/.

For someone who thinks beginners should start on the simple stuff, this
takes the cake: If he thinks the only way to write code for an OS that
doesn't accept flat-binary executables (that is, all modern OSes except
the last remaining DOS clones) is to roll your own headers, how does he
expect beginners to /ever/ write 32-bit assembly? Does he want them to
stick with V86 DOS mode until they can convince themselves to write
their own headers each time?

Bah. What a loon.

>
> You were on the money, August, with that "dick waving" machismo
> comment...I mean, he may claim that his 68K-inspired syntax is all
> about "Motorola have a cleaner syntax" but, in the end, we _ALL KNOW_
> that it's really a case of: "Look how hard I am! I can use totally
> confusing syntax! I know more than one assembly language, as you can
> see, so I'm a really hard guru-type person!"...and all that kind of
> nonsense...thus, his opinions as to what is best for a beginner to use
> are, as you've rightly pointed out, hardly things to take all that
> seriously: "beginners should eat steel nails and pour raw coffee down
> their throats or they are just wimps!! And there's only room for 'hard
> men' in assembly programming!!" ;)

I'm a fan of Motorola's 68k architecture. Hell, I'm a fan of Digital's
(now Compaq's) PDP and VAX architectures, may they rest in peace. But as
much as I'd want to own a 68k-based home machine (or maybe a nice VAX...
;) ), I own an AMD Duron and so I write assembly for an x86 clone. I
don't try to fool myself with a syntax that doesn't fit the architecture.

I'm not saying Herbert doesn't have a right to use whatever syntax he
wants, but in this newsgroup it's rather rude to use something so
bizarre it needs explanation every time it's trotted out. Especially if
you never fully explain it. (For example, how do registers work on his
system? Is r0 the name of ah, ax, or eax? If r0 is ax or eax, how does
he access ah and al seperately? See what I mean about fooling with a
syntax that doesn't fit the architecture?)

>
> Beth :)

Matt Taylor

unread,
Jan 27, 2004, 9:26:10 PM1/27/04
to
"Bx.C" <nu...@the.void> wrote in message
news:lTjRb.28647$lh3....@bignews5.bellsouth.net...
<snip>

> yes, but i must say... i seriously doubt the rest of my A+ class are ready
> for this info..... i tried having a logical technical discussion about the
> relevance of Microsoft DOS in current and future operating systems (while
> keeping in mind that v86 sessions won't run in Long mode on 64-bit
> processors).... and while i myself debated both ways... that Microsoft
would
> keep some form of DOS, even while running under the most secure modes of
> later processors, but may re-work it to be a simple 32-bit command line
> interface run under protected mode only, leaving out the possibility for
> switching between v86 sessions and 64-bit mode... which would be a very
> nasty job to keep track of, trying to jump back and forth constantly...
(and
> yet, they may keep the current real mode or v86 mode compatible DOS simply
> for pre-winboot tasks.... disk maintenance... registry repair... password
> recovery... etc) ..... the person i was sitting with, discussing this
> with... seemed lost in the first few minutes...

They wrote an x86 emulator back when NT was first written. Back then, RISC
architectures were expected to displace x86, and they needed backward
compatibility. As I understand, 64-bit Windows will use this emulator to
emulate DOS/Win16.

> and right now.... looking back... i think i had too much coffee this
> morning...

Impossible!

-Matt


Tim Roberts

unread,
Jan 28, 2004, 1:50:20 AM1/28/04
to
"Matt Taylor" <pa...@tampabay.rr.com> wrote:
>
>They wrote an x86 emulator back when NT was first written. Back then, RISC
>architectures were expected to displace x86, and they needed backward
>compatibility. As I understand, 64-bit Windows will use this emulator to
>emulate DOS/Win16.

Actually, it appears that 64-bit Windows simply will not support DOS or
Win16 apps. I made a statement about this in one of the MVP newsgroups,
and a fellow who was running a Win64 system did a couple of experiments for
me that seemed to confirm this.

I was surprised, since I would guess the incremental cost of DOS/Win16
support to be near nil.

pH

unread,
Jan 28, 2004, 11:32:08 AM1/28/04
to
On Tue, 27 Jan 2004 23:47:30 +0000 (UTC), August Derleth <s...@sig.now> wrote:

[...]

>I'm not saying Herbert doesn't have a right to use whatever syntax he
>wants,

Perish the thought.

> but in this newsgroup it's rather rude to use something so
>bizarre

<g>

> it needs explanation every time it's trotted out.

And on top of that, use it as an "example" illustrating why assembler
for Windows is a bad idea.

> Especially if
>you never fully explain it.

Honestly, does it matter? I mean... beyond a certain point--and it's a
point which lies very near the starting line--does it really frickin' matter...

"Hey, it might be silly, but it makes no sense!" ;)

Arguing for the sake of arguing... is there a specific word for that? A
thoroughly unlovely conglomeration... sophistic, argumentative, contentious
wrangling... needs its own word.

Jeff

http://www.jefftturner.com

arargh4...@now.at.arargh.com

unread,
Jan 28, 2004, 4:49:27 PM1/28/04
to
On Mon, 26 Jan 2004 05:26:41 +0000 (UTC), Bjarni Juliusson
<bjarni...@update.ferret.uu.se> wrote:

>I'm in the mood for a little nitpicking.
>
>> Intel started long ago with the 4040, which was used only in
>
>They started with the world's first microprocessor, the 4004, in 1971.
>Development had started in 1969. It was a 4 bit chip. In 1972 Intel
>introduced the 8 bit 8008.
>
>> calculators. Later, the 8080 was designed and used in CP/M based
>
>Correct. This was in 1974. The 8080 was an 8 bit processor with 16 bit
>addresses, and it was the model for the incredibly popular Z80.
>
>> systems, then came along the 8088 (and soon after 8086), which was
>> used on PC's, XT's, and clones. These systems used 16-bit
>> instructions on what was an 8-bit CPU (or in the case of the 8086 a
>> 16-bit cpu with an 8-bit bus), and in order to access more memory than
>
>Very common mistake. The 8086 was released in 1978, and it is a true 16
>bit processor. To allow for cheaper circuit boards, Intel released the
>8088 in 1979. This is an exact copy of the 8086, but with an 8 bit
>external data bus. It is a 16 bit processor inside, just like the 8086.
>
>> possible with a single 16-bit register, Intel used segment:offset
>> scheme of doing things. The segment was shifted 4 bits and added to
>> the offset to point to the actual memory location. This meant that
>> any given memory location could be referenced in several different
>> ways, eg.
>

Somewhere about here came the 80186 & 88.

>Now this is all true. Then came the 80286 with 16 bit protected mode,
>then the 80386 with 32 bit protected mode, and the rest have essentially
>been fast 386s.

--
Arargh401 at [drop the 'http://www.' from ->] http://www.arargh.com
BCET Basic Compiler Page: http://www.arargh.com/basic/index.html

To reply by email, remove the garbage from the reply address.

August Derleth

unread,
Jan 30, 2004, 1:58:51 PM1/30/04
to
Frank Kotler wrote:

> Beth wrote:
>
>> You were on the money, August, with that "dick waving" machismo
>> comment...
>
>
> No he wasn't! (in my ever-so-humble opinion, of course!) I knew you'd be
> attracted to that phrase, Beth. If my dick were as small as my .com
> files, I'd keep it in my pants where it belongs!

/This/ brings up odd images. I suppose I initiated the whole `dick
size'/`binary size' thing, but it doesn't make much sense.

>
> Seriously, this "executable size doesn't matter because Windows wastes
> memory/storage in big chunks anyway" doesn't wash. To be sure, cutting
> your "hello world" from 30 bytes to 27 doesn't make any difference, but
> cutting ten percent off your megabyte executable *does*!

I never mentioned Windows. Linux, with its ext2 filesystem, allocates
disk space in chunks no smaller than one Kibibyte (1024 bytes), and
usually something like four Kibibytes. (I don't think ext3 changes this
basic philosophy.) Why? Because disk access is slow, and RAM is fast. If
you can shove relatively large blocks of the disk into RAM at once and
thereafter access RAM, you can get big wins in performance. There's no
way in hell a modern non-embedded OS is going to access the disk for
anything less than one Kib, even if it means wasting both RAM and disk
space.

Now that that's off my chest...

Shaving ten percent off a multi-Meb executable is perhaps laudible, but
Moore's Law or something very like it applies to disks, too. You shrink
the size of the program from five Mebs (5,242,880 bytes) to 4.9 Mebs
(4,718,592 bytes). Meanwhile, your client is buying 120 Gibibyte* hard
drives for his machines, and your size saving gets lost in the underflow.

*That's 120 * 2**30, an eleven-digit number. I own one, and I haven't
even been able to quarter-fill it in over a year of trying. ;) I can
safely say I now own a storage device whose capacity is beyond my
comprehension.

>
> If the professionals wrote software with a "don't care about size"
> attitude like that, we'd see... Oh. Right. Nevermind...

Usually, it doesn't matter. That doesn't mean people should be lazy
about these things: Quite the opposite, it means that people should use
the techniques that will give the best /balance/ between the various
factors in program development. And raw size is usually /not/ a
heavily-weighted factor, especially when compared to future
maintainability and security. Or, to drag this back to the original
tangent, ease of using the code to teach students of assembly language.

Since I'm not convinced Microsoft has mastered /any/ of those things
(bloat control, maintainability, or security, among other important
factors), I will laugh at your little joke. :D

Now for a little aside and confession: When I'm writing assembly, I will
go back and optimize for size and speed even after I've decided the
program is done, finished, and completed. (Needless to say, these are my
own personal programs I'm messing with.) I'll replace things like
mov eax, 0FFFFFFFFh
with
xor eax, eax
dec eax
simply because I can't stand to see 32 bits simply used to store a
constant value. I've never gotten into cycle-counting, partly because my
knowledge would be obsolete before it's mastered and partly because I
don't want to rewrite all of my programs /again/. ;)

>
> Best,
> Frank

C

unread,
Jan 30, 2004, 6:13:15 PM1/30/04
to
August Derleth <s...@sig.now> wrote in message news:<nnsSb.522$rK6...@fe02.usenetserver.com>...

I'll replace things like
> mov eax, 0FFFFFFFFh
> with
> xor eax, eax
> dec eax


"OR EAX, -1" is better (encoded as 83C8FF).
It is the same length, but is executed as
only one instruction and therefore can pair
better. :-)

C
2004-01-30

August Derleth

unread,
Jan 31, 2004, 12:17:37 AM1/31/04
to
Tim Roberts wrote:

> "Matt Taylor" <pa...@tampabay.rr.com> wrote:
>
>>They wrote an x86 emulator back when NT was first written. Back then, RISC
>>architectures were expected to displace x86, and they needed backward
>>compatibility. As I understand, 64-bit Windows will use this emulator to
>>emulate DOS/Win16.
>
>
> Actually, it appears that 64-bit Windows simply will not support DOS or
> Win16 apps.

And Linux does and will. Well, I don't know about Win16. dosemu is
focused on 16/32-bit textmode DOS, and WINE is Win32-only so far as I
know. But a small convergence between the virtual machine folks (dosemu)
and the API folks (WINE) should fill the gap fairly well.

(Oh, and note that neither dosemu nor WINE do actual emulation. They
both let the x86 CPU they assume the hardware machine has execute the
opcodes, and fill in details like establishing the API and, if the
software wants it, V86 mode.* If you want emulation, you need Bochs.
Maybe IA-64 will require something like Bochs to execute IA-16/32 code.)

*(In fact, Linux has a syscall to shift a specific process into V86
mode. So far as I know, only dosemu uses it.)

John H. Guillory

unread,
Jan 31, 2004, 2:42:34 PM1/31/04
to
On Tue, 27 Jan 2004 17:12:21 +0000 (UTC), "Bx.C" <nu...@the.void>
wrote:

>> > hehe... yah... my A+ instructor told us just the other day that a 586 is
>> > simply two 486's put together in one package.... (what i think he was
>> > actually trying to explain at the time, was the fact that the 586 had
>two
>> > instruction pipelines.... but he didn't do a very good job.... looking
>> > around the room, he left the other students more confused than
>before)...

Just one small reason why I usually consider A+ and MSCE
certifications worthless.... Anyone flashing an A+ or MSCE
certification to me gives me the impression they don't know anything
and are relying on paying someone some money to say they passed the
exam. But then again, maybe if you seen "What" passes the A+ and MSCE
exams in these parts and can't understand how to configure a computer,
install windows, etc... Not to put the other guy down, just that I've
had to straighten out too much work from idiots who flash a MSCE
certificate and A+ certificate making people think they know what
they're doing....

John H. Guillory

unread,
Jan 31, 2004, 2:42:58 PM1/31/04
to
On Mon, 26 Jan 2004 05:26:41 +0000 (UTC), Bjarni Juliusson
<bjarni...@update.ferret.uu.se> wrote:

>Correct. This was in 1974. The 8080 was an 8 bit processor with 16 bit
>addresses, and it was the model for the incredibly popular Z80.

O.k. so I transposed a couple of numbers on the 4004 and left out the
8008.... ;-)

>> systems, then came along the 8088 (and soon after 8086), which was
>> used on PC's, XT's, and clones. These systems used 16-bit
>> instructions on what was an 8-bit CPU (or in the case of the 8086 a
>> 16-bit cpu with an 8-bit bus), and in order to access more memory than
>
>Very common mistake. The 8086 was released in 1978, and it is a true 16
>bit processor. To allow for cheaper circuit boards, Intel released the
>8088 in 1979. This is an exact copy of the 8086, but with an 8 bit
>external data bus. It is a 16 bit processor inside, just like the 8086.

As I said, the 8086 was a 16-bit CPU, but it very much had an 8-bit
BUS to all other chips. It was not a TRUE 16-bit processor, as a true
16-bit processor would have a 16-bit data path everywhere....

>> possible with a single 16-bit register, Intel used segment:offset
>> scheme of doing things. The segment was shifted 4 bits and added to
>> the offset to point to the actual memory location. This meant that
>> any given memory location could be referenced in several different
>> ways, eg.
>
>Now this is all true. Then came the 80286 with 16 bit protected mode,
>then the 80386 with 32 bit protected mode, and the rest have essentially
>been fast 386s.

Yes, I could have swore I mentioned protected mode in the original
message...

Matt Taylor

unread,
Jan 31, 2004, 3:59:21 PM1/31/04
to
"August Derleth" <s...@sig.now> wrote in message
news:7HFSb.240$JA...@fe02.usenetserver.com...

> Tim Roberts wrote:
>
> > "Matt Taylor" <pa...@tampabay.rr.com> wrote:
> >
> >>They wrote an x86 emulator back when NT was first written. Back then,
RISC
> >>architectures were expected to displace x86, and they needed backward
> >>compatibility. As I understand, 64-bit Windows will use this emulator to
> >>emulate DOS/Win16.
> >
> >
> > Actually, it appears that 64-bit Windows simply will not support DOS or
> > Win16 apps.
>
> And Linux does and will. Well, I don't know about Win16. dosemu is
> focused on 16/32-bit textmode DOS, and WINE is Win32-only so far as I
> know. But a small convergence between the virtual machine folks (dosemu)
> and the API folks (WINE) should fill the gap fairly well.

They're going to have to use a different strategy in long mode. Long mode
does not support v8086 mode.

> (Oh, and note that neither dosemu nor WINE do actual emulation. They
> both let the x86 CPU they assume the hardware machine has execute the
> opcodes, and fill in details like establishing the API and, if the
> software wants it, V86 mode.* If you want emulation, you need Bochs.
> Maybe IA-64 will require something like Bochs to execute IA-16/32 code.)

<snip>

Itanium actually has a mode to emulate IA-32, but it's absolutely awful. I
have heard that Merced could execute IA-32 code about as fast as a 486.
Windows for IA-64 emulates IA-32 code now.

-Matt


Bob Masta

unread,
Feb 1, 2004, 10:16:02 AM2/1/04
to
On Sat, 31 Jan 2004 19:42:58 +0000 (UTC), "John H. Guillory"
<jo...@mlc-hosting.net> wrote:

>As I said, the 8086 was a 16-bit CPU, but it very much had an 8-bit
>BUS to all other chips. It was not a TRUE 16-bit processor, as a true
>16-bit processor would have a 16-bit data path everywhere....

The 8086 was a true 16-bit processor, with a 16-bit bus. You are
thinking of the 8088, which was identical internally but only had
an 8-bit bus. IBM chose this for cost reasons; the 8086 was never
a success itself. Incidentally, the same short-bus idea was
resurrected when 32 bits came out, in the form of the 386SX;
you had to get a 386DX to get a 32-bit bus. The SX monniker
was later applied to the 486 to indicate it was missing the NPU,
even though the bus was the full 32 bits.


Bob Masta
dqatechATdaqartaDOTcom

D A Q A R T A
Data AcQuisition And Real-Time Analysis
www.daqarta.com

Bjarni Juliusson

unread,
Feb 1, 2004, 5:24:51 PM2/1/04
to
> I hope this has undone some of the confusion/damage your
> instructor inflicted. Of course, I have attempted to explain
> in a few paragraphs what would normally take several chapters,
> therefore many details have been elided. To fill in the many
> gaps I suggest you have a look at the book "Hennessy, J., and
> Patterson, D. Computer Architecture - A Quantitive Approach.
> Morgan Kaufmann Publishers Inc., 1990". Though it is getting
> a little old, it is still the definitive text on the subject.
> (I think a second edition was published around 1996.)

There was even a third edition in 2003.


--
Remove the furry animal from my address to send email:

bjarni...@update.ferret.uu.se

Tim Roberts

unread,
Feb 2, 2004, 1:02:09 AM2/2/04
to
s...@sig.now wrote:

>Tim Roberts wrote:
>
>> Actually, it appears that 64-bit Windows simply will not support DOS or
>> Win16 apps.
>
>And Linux does and will. Well, I don't know about Win16. dosemu is
>focused on 16/32-bit textmode DOS, and WINE is Win32-only so far as I
>know.

Quite correct.

>(Oh, and note that neither dosemu nor WINE do actual emulation. They
>both let the x86 CPU they assume the hardware machine has execute the
>opcodes, and fill in details like establishing the API and, if the
>software wants it, V86 mode.* If you want emulation, you need Bochs.
>Maybe IA-64 will require something like Bochs to execute IA-16/32 code.)
>
>*(In fact, Linux has a syscall to shift a specific process into V86
>mode. So far as I know, only dosemu uses it.)

Actually, the vm86 syscall is used more than you might think. XFree86 uses
the vm86 syscall to call into the video BIOS. Most of the drivers use it
to get BIOS information, and several actually use the video BIOS to do mode
switching.

RoWsRaIrTiEo

unread,
Feb 16, 2004, 1:32:23 PM2/16/04
to
On Sun, 25 Jan 2004 +0000 (UTC), August Derleth <s...@sig.now> wrote:
>Herbert Kleebauer wrote:
>> August Derleth wrote:
>>>Herbert Kleebauer wrote:
>>
>>>>But even if an Intel 32 bit processor is used, a beginner always
>>>>should start learning assembly programming in real or V86 mode and
>>>>not in protected mode.
>>>
>>>Should all new drivers start out with a Model-T, too?
>>
>>
>> I didn't speak of an ancient 8086 processor. Even the newest x86 processor
>> supports the three modes: real/V86/protected mode. And you can use the
>> 32 bit instructions and all the 32 bit addressing modes in any of this
>> three modes. So it doesn't matter at all which of this modes you use to
>> LEARN assembly programing. But it is important to use an operating
>> system with a simple interface so you can concentrate on the language
>> of the processor and don't have to spend much more time with the OS
>> interface than with the processor instructions. And the int21
>> interface is much easier to use (and still supported in the newest
>> MS operating systems for V86 mode) than the Win32 interface.

[]

>And if you are using the 32-bit addressing modes and opcodes in V86
>mode, why not drop the last pretenses of `simplicity' and move into
>32-bit protected mode? It really isn't that difficult, and it can save
>you from shooting yourself in the foot: In protected mode, it becomes
>impossible to scribble on memory you don't own. What could have been an
>OS-corrupting error becomes a much easier to understand segfault error
>on Linux, for example, because Linux has nothing to do with V86. (Linux
>has a syscall to move a specific process into V86 mode, which to my
>knowledge is only used by one program: dosemu, the virtual x86 system
>capable of hosting a DOS-like OS plus BIOS. Other than that, Linux is
>just another Unix.)

So why, in Linux, programs with ID=0 would not read or write in others
memory programs? Only for processor reasons?

>/Au contraire/: Assembly isn't a stand-alone language anymore in most
>cases. Interfacing with an HLL (and I don't know how HL C is ;) ) is not
>only an exercise in simplicity (via libc), it's practice in how to
>structure your own subroutines (learn which registers you must save,
>learn how to create and destroy a stack frame, learn how to access
>arguments, and learn how to properly return a value) and create your own
>libraries.
>
>Learning the instruction set isn't hard.

I think there are too instructions [and too instructions that do the
same thing] even in 8086cpu; I can full program use 20% of
instructions

>Learning memory is more
>difficult, but 32-bit protected mode makes it easier in addition to
>giving you a nice net. Learning how to structure a program logically and
>how to write consistent code that makes use of the environment is more
>difficult, and it isn't something DOS is especially good at teaching.

I like 8086 asm programming more than 80x86 (x>=1) programming
perhaps it is because I can mix code and data. I think that 8086 is
better planed but this is the first impression of a newbie

>>>>As an example a simple program which reads from stdin and writes
>>>>to stdout, converting all upper case characters to lower case.
>>>>To make it compatible with the win32 version, it uses mostly
>>>>32 bit instructions. But even then the generated executable
>>>>file size is only 109 bytes.
>>>
>>>Executable size? Dick-waving nonsense. Blocks on a hard drive are larger
>>>than that. You gain nothing by stripping the binary to less than one or
>>>two Kibibytes.

I **not agree** for principle

>> You are right, it doesn't matter how much disc space is needed for
>> a program. But we are speaking about learning assembly programming.
>> And it does matter if a beginner has to understand 1000 or only 100
>> bytes to successfully run his first assembler program.

Tim Roberts

unread,
Feb 16, 2004, 11:54:07 PM2/16/04
to
RoWsRaIrTiEo <n...@esist.eeee> wrote:
>
>So why, in Linux, programs with ID=0 would not read or write in others
>memory programs? Only for processor reasons?

Oh, they certainly CAN do so, although it is a lot of work.

Page tables are swapped when a process changes, so the pages belonging to
other processes are no longer in the page tables. The pages are still in
memory, but they are temporarily "orphaned". A suitably motivated
user-mode root process could certainly scan the system to figure out what
physical pages belong to other processes and write on them, but there are
so many other interesting and pesky things one can do in a root process
that this just isn't worth the trouble.

Bob Masta

unread,
Feb 17, 2004, 8:35:59 AM2/17/04
to
On Mon, 16 Feb 2004 18:32:23 +0000 (UTC), RoWsRaIrTiEo
<n...@esist.eeee> wrote:

>
>I like 8086 asm programming more than 80x86 (x>=1) programming
>perhaps it is because I can mix code and data. I think that 8086 is
>better planed but this is the first impression of a newbie


It is perfectly possible to mix code and data on any x86 system.
In the DOS days there was a strong incentive *not* to mix them
on programs above 64K in size, since you could typically keep
all your data in one data segment and access it from your code
segment(s). Or you could keep different data in different data
segments if you really had a lot, and just change DS (or ES) as
needed.

In 32-bit protected mode programming you are effectively mixing
code and data, since there is only one huge memory space, and
all the segment selectors are set the same (on Windows, anyway).
By default your assembler expects you to declare your data and
code in separate sections, but they can be easily combined if
you have some need to do so. (One reason might be self-modifying
code for security purposes.) You now have a much bigger sandbox
to play in, and those wonderful 32-bit wide instructions at no extra
(prefix) cost!

Bx.C

unread,
Feb 17, 2004, 2:13:50 PM2/17/04
to

"Bob Masta" <NoS...@daqarta.com> wrote in message
news:40321562...@news.itd.umich.edu...

from a memory access point of view, though... isn't the L1 cache separated
into a code cache and a data cache? (or is my mind fried from too much
nintendo? or both?)

0 new messages