From: Tom on
Hello,
For some time now I have been learning assembly on my own using
Webster. So far I have managed to build a small paper-and-pencil uP and
read/comprehend most of the material from the 16-bit DOS version of AoA
(I understand DOS is obsolete, but I have found it simpler to start
with, hope to do better in the future).

Would you be kind enough as to help me clarify the following points
(regarding real mode programming):

1. Why do segment registers hold segments' paragraph numbers rather
than their absolute addresses?

2. In Chapter 6 of AoA (The instruction set, 6.11.1 Simple arithmetic
I) Mr. Hyde gives an example of code in which he declares a procedure
MAIN, which is duly terminated with "Main endp". What does the second
"end Main" expression stand for? Why is this procedure not called? Or
is it?

Thank you very much for all kind replies.

Kindest regards,
Tom

From: NoDot on
Tom wrote:
> Hello,

Greetings

> 1. Why do segment registers hold segments' paragraph numbers rather
> than their absolute addresses?

It's how real mode operates. Intel chose this mode because it's an easy
way to extend the memory to 1M without much complexity.

> 2. In Chapter 6 of AoA (The instruction set, 6.11.1 Simple arithmetic
> I) Mr. Hyde gives an example of code in which he declares a procedure
> MAIN, which is duly terminated with "Main endp". What does the second
> "end Main" expression stand for? Why is this procedure not called? Or
> is it?

I haven't read the 16-bit edition for a long time. Randall'll have to
answer you on this one.

> Thank you very much for all kind replies.

Kind? Not here, unfortunately. At comp.lang.asm.x86, they're kind.

> Kindest regards,
> Tom


--
The above was written by NoDot.

Visit the Website of NoDot:
<www.geocities.com/nodot1989/>
From: Herman Dullink on
> 1. Why do segment registers hold segments' paragraph numbers rather
> than their absolute addresses?
This is Intel's first attempt to break the 64KB limit of a 16-bit CPU. Using
paragraph addresses expands the total addressable space to 1MB. This allows
definition of several variable sized segments. Because of lack of
protection, it's possible to address outside the segment...
This is only the case on 8086 and compatible CPUs, and in Real Mode on 80286
and compatible CPUs. In protected mode, segment registers hold an index in a
segment descriptor table, which not only hold a base (absolute) address, but
also its size (which is checked for every access) and privileges
(level,read/write/execute).


> What does the second
> "end Main" expression stand for? Why is this procedure not called? Or
> is it?
The "end" is to tell the assembler that this is the end of the source code.
The "Main" is to set the entry point. The linker will put this address in
the header of the executable file. DOS will then execute from this address
when this file is executed.
If e.g. you would put a 2nd procedure in this source file (MyMain) and use
the name of that 2nd procedure after end, then that 2nd procedure is run,
and not "Main".

H


From: Frank Kotler on
Tom wrote:
>
> Hello,
> For some time now I have been learning assembly on my own using
> Webster. So far I have managed to build a small paper-and-pencil uP and
> read/comprehend most of the material from the 16-bit DOS version of AoA
> (I understand DOS is obsolete, but I have found it simpler to start
> with, hope to do better in the future).

I agree. You'll find some people feel that you shouldn't
"waste" any time at all learning dos. I'd agree that it
isn't worthwhile learning "dos", per se, in any depth, but I
agree with you that it's "simpler" to interface with dos
than with Windows or Linux. Linux has an "int 80h" interface
- similar to the dos "int 21h" interface, but Windows
requires calling a "Dynamically Linked Library". Easy enough
to *do*, but harder to understand what you're *doing* (IMO).

32-bit programming, in itself, is *easier* than 16-bit
programming - no worries about segments, and the addressing
modes are much more flexible. Once you feel ready to make
the switch (I'd learn how "call" and "ret" work - how to use
the stack to pass parameters, and keep the stack "sane"), I
think you'll like 32-bit programming... so don't waste *too*
much time with dos!

> Would you be kind enough as to help me clarify the following points
> (regarding real mode programming):
>
> 1. Why do segment registers hold segments' paragraph numbers rather
> than their absolute addresses?

Funny you should ask... (see the thread about ".model" in
Tasm). It's either:

1) Because that's the chip the market *demanded* (at *that*
time). Easy "upgrade path" for 8080 code, and ability to use
more than 64k without "wasting" much memory. (my theory) Or:

2) Intel was really stupid. (Beth's theory)

In any case, I think we agree that it wouldn't be a sensible
way to design a chip *now*. For purposes of *using* it,
rather than trying to improve on Intel's design, just assume
"that's the way it is".

> 2. In Chapter 6 of AoA (The instruction set, 6.11.1 Simple arithmetic
> I) Mr. Hyde gives an example of code in which he declares a procedure
> MAIN, which is duly terminated with "Main endp". What does the second
> "end Main" expression stand for?

It isn't really "second" - "end" is different from "ends".
"end" tells Masm that your code ends - anything after that
is ignored - *and* the label after "end" defines where the
entrypoint to the code is - this example probably doesn't do
it, but you could put subroutines *before* your "Main", and
execution would still start at "Main:"...

For comparison - a ".com" file always starts at the
beginning of your code. Other assemblers indicate the
entrypoint differently - Nasm, for example, uses "..start:"
and doesn't use "end" or "ends" at all.

> Why is this procedure not called? Or
> is it?

No, it's not. Personally, I think "Main" is a potentially
confusing name to use, if it isn't a "C-style" main - that
is, called (so a "ret" or "retf" will exit it), and with
argc, argv, and envp on the stack. That isn't the situation
with an asm program unless you write the code to do it.
Or... you can write an asm file using "main" (probably have
to be "_main", actually), assemble it to an .obj file, and
use a C compiler to link it... *with* C startup code. In
this case, "main" needs to be named "main". Otherwise, *I'd*
call it something else.

> Thank you very much for all kind replies.

You're welcome. Thank *you* for the on-topic question!
Ignore any "less-than-kind" replies you get, and ignore any
newbie twirps who advise you to take your questions to clax!
We *do* discuss assembly language around here...
sometimes...

Best,
Frank
From: Herbert Kleebauer on
Frank Kotler wrote:>

> 32-bit programming, in itself, is *easier* than 16-bit
> programming - no worries about segments, and the addressing
> modes are much more flexible. Once you feel ready to make
> the switch (I'd learn how "call" and "ret" work - how to use
> the stack to pass parameters, and keep the stack "sane"), I
> think you'll like 32-bit programming... so don't waste *too*
> much time with dos!

It is not fair to tell this old but wrong fairytale
to newcomer. DOS doesn't restrict you in any way to
to 16 bit operand size or 16 bit addressing modes
and you are also not bound to real/v86 mode.
For learning assembly programming, there is nearly
no difference between using DOS or Windows: in
DOS you are restricted in the amount of usable memory
(but this really doesn't matter for learning assembly
programming) and there is much less overhead in DOS
than in Windows (executable file format, OS API) which
makes it much easier to start assembly programming in DOS.

As an example a program which calculates the md5 hash
for stdin. There is no way to tell if this is a Win32
or a DOS program. It can be assembled for both, all
you have to do is to insert the proper getc, putc and
exit functions.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; md5.mac ;;
;; calculate md5 hash for stdin (see RFC 1321) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


bclr.w #10,sr ; clear direction flag for auto increment
eor.l r4,r4 ; low bit count
eor.l r5,r5 ; high bit count
_11: move.l #64,r2 ; read 64 bytes
move.l #buf,r6 ; pointer to 64 byte buffer
_10: bsr.l getc ; read char from stdin
move.b r0,(r6)+-{s1} ; store in buffer and increment pointer
cmpq.l #-1,r0 ; end of file
beq.b _20 ; yes
addq.l #1,r4 ; incr total number of read bytes
addcq.l #0,r5
dbf.l r2,_10 ; repeat until 64 bytes read
bsr.l md5 ; update md5 hash for 64 bytes read
br.b _11 ; next 64 byte block


_20: dsl.l #3,r5<r4 ; total number of read bits
lsl.l #3,r4

move.b #$80,-1.b(r6) ; replace EOF by $80
_31: move.l r6,-(sp) ; save pointer
_30: cmp.l #buf+63,r6
bhi.b _32
move.b #0,(r6) ; fill rest of buffer with 0
inc.l r6
br.b _30

_32: move.l (sp)+,r6
cmp.l #buf+56,r6 ; 8 bytes free in buffer?
bls.b _40 ; yes
bsr.l md5 ; update md5 hash for 64 bytes in buffer
move.l #buf,r6 ; need a fresh 64 byte block
br.b _31

_40: move.l r4,buf+56 ; insert bit count in last 8 bytes
move.l r5,buf+60
bsr.l md5 ; update md5 hash for 64 bytes in buffer

move.l #a,r5 ; pointer to hash value
move.l #16,r2 ; 16 byte hash
_60: move.b (r5),r0 ; next byte of hash
lsr.b #4,r0 ; upper nippel
bsr.l _70 ; convert to hex and output
move.b (r5)+-,r0 ; get byte again and inc pointer
and.b #$0f,r0 ; lower nippel
bsr.l _70 ; convert to hex and output
dbf.l r2,_60 ; all 16 byte done?

bsr.l exit

_70: add.b #'0',r0 ; convert to ascii
cmp.b #'9',r0 ; lower same '9'
bls.b _50 ; yes, then ok
add.b #'a'-'9'-1,r0 ; no, convert to a-f
_50: bsr.l putc
rts.l


md5: ; this is a 1:1 implementation of the code in RFC 1321
; so no documentation is given here
move.l r5,-(sp) ; don't modify r4 and r5
move.l a,r0
move.l r0,aa
move.l b,r0
move.l r0,bb
move.l c,r0
move.l r0,cc
move.l d,r0
move.l r0,dd

move.l #a,r5
eor.l r3,r3
_10: cmp.b #15,r3
bhi.b _20
move.l 4.b(r5),r0
move.l r0,r1
and.l 8.b(r5),r1
not.l r0
and.l 12.b(r5),r0
or.l r1,r0
br.b _50

_20: cmp.b #31,r3
bhi.b _30
move.l 12.b(r5),r0
move.l r0,r1
and.l 4.b(r5),r1
not.l r0
and.l 8.b(r5),r0
or.l r1,r0
br.b _50

_30: cmp.b #47,r3
bhi.b _40
move.l 4.b(r5),r0
eor.l 8.b(r5),r0
eor.l 12.b(r5),r0
br.b _50

_40: move.l 12.b(r5),r0
not.l r0
or.l 4.b(r5),r0
eor.l 8.b(r5),r0
_50:

add.l (r5),r0
movu.bl index(r3),r6
add.l buf(r6*4),r0
add.l sin(r3*4),r0
move.b shift(r3),r2
rol.l r2,r0

add.l 4.b(r5),r0
move.l r0,(r5)
move.l r0,16.b(r5)
subq.l #4,r5
cmp.l #b0,r5
bhs.b _60
addq.l #16,r5
_60: inc.b r3
cmp.b #64,r3
blo.l _10
move.l aa,r0
add.l r0,a
add.l r0,a0
move.l bb,r0
add.l r0,b
add.l r0,b0
move.l cc,r0
add.l r0,c
add.l r0,c0
move.l dd,r0
add.l r0,d
add.l r0,d0
move.l (sp)+,r5
rts.l

b0: dc.b $89,$ab,$cd,$ef
c0: dc.b $fe,$dc,$ba,$98
d0: dc.b $76,$54,$32,$10
a: dc.b $01,$23,$45,$67
b: dc.b $89,$ab,$cd,$ef
c: dc.b $fe,$dc,$ba,$98
d: dc.b $76,$54,$32,$10
a0: dc.b $01,$23,$45,$67


index: dc.b 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15
dc.b 1, 6,11, 0, 5,10,15, 4, 9,14, 3, 8,13, 2, 7,12
dc.b 5, 8,11,14, 1, 4, 7,10,13, 0, 3, 6, 9,12,15, 2
dc.b 0, 7,14, 5,12, 3,10, 1, 8,15, 6,13, 4,11, 2, 9

shift: dc.b 7,12,17,22, 7,12,17,22, 7,12,17,22, 7,12,17,22
dc.b 5, 9,14,20, 5, 9,14,20, 5, 9,14,20, 5, 9,14,20
dc.b 4,11,16,23, 4,11,16,23, 4,11,16,23, 4,11,16,23
dc.b 6,10,15,21, 6,10,15,21, 6,10,15,21, 6,10,15,21

sin:
dc.l $d76aa478, $e8c7b756, $242070db, $c1bdceee, $f57c0faf, $4787c62a
dc.l $a8304613, $fd469501, $698098d8, $8b44f7af, $ffff5bb1, $895cd7be
dc.l $6b901122, $fd987193, $a679438e, $49b40821, $f61e2562, $c040b340
dc.l $265e5a51, $e9b6c7aa, $d62f105d, $02441453, $d8a1e681, $e7d3fbc8
dc.l $21e1cde6, $c33707d6, $f4d50d87, $455a14ed, $a9e3e905, $fcefa3f8
dc.l $676f02d9, $8d2a4c8a, $fffa3942, $8771f681, $6d9d6122, $fde5380c
dc.l $a4beea44, $4bdecfa9, $f6bb4b60, $bebfbc70, $289b7ec6, $eaa127fa
dc.l $d4ef3085, $04881d05, $d9d4d039, $e6db99e5, $1fa27cf8, $c4ac5665
dc.l $f4292244, $432aff97, $ab9423a7, $fc93a039, $655b59c3, $8f0ccc92
dc.l $ffeff47d, $85845dd1, $6fa87e4f, $fe2ce6e0, $a3014314, $4e0811a1
dc.l $f7537e82, $bd3af235, $2ad7d2bb, $eb86d391



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; unitialized data ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



aa: blk.l 1
bb: blk.l 1
cc: blk.l 1
dd: blk.l 1


buf: blk.b 64


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; end of md5.mac ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 |  Next  |  Last
Pages: 1 2 3 4 5 6 7 8 9 10 11
Prev: stricmp
Next: Killing Explorer