F3U@PSUVMB.BITNET (11/04/87)
I am looking for some functions when called from a C program, will: 1) read (peek) memory directly when supplied with an address. Returns with the value at specified address. and 2) write (poke) memory directly when supplied with an address and a byte value. I am using Microsoft C 4.0 on an AT&T 6300 PLUS. Routines in C or Assembler OK. Thanks in advance. Frank F3U@PSUVMB.BITNET
kwok@iris.ucdavis.edu (Conrad Kwok) (11/07/87)
When you are using C, you don't need any special routine to read memory. All you need to do is to declare a pointer (near or far depending on the address) and then you may read or write to that location using normal assignment statements. Here is an example to read the value at location 0xC000:0x0100 char far *ptr; ptr = (char far *) 0xC0000100L; printf("Value at 0xC000:0x0100 is %d\n", *ptr); The above above should also works for Turbo C. -- Conrad internet: kwok@iris.ucdavis.edu csnet: kwok@ucd.csnet csnet: kwok%iris.ucdavis.edu@csnet.relay uucp: {seismo, uunet, lll-lcc, ...}!ucdavis!iris!kwok
platt@emory.uucp (Dan Platt) (11/08/87)
In article <24261F3U@PSUVMB> F3U@PSUVMB.BITNET writes: >I am looking for some functions when called from a C program, will: > 1) read (peek) memory directly when supplied with > an address. Returns with the value at specified address. > and > 2) write (poke) memory directly when supplied with an > address and a byte value. > >I am using Microsoft C 4.0 on an AT&T 6300 PLUS. Routines >in C or Assembler OK. The way I did it was to define a routine that loads a pointer with a value pointed to by a segment/offset... __________________________________________________________________ far char * mem_pt(seg,offst) /* this may be coerced */ short seg,offst; { union { struct { short: ofst,sg; /* these may be backwards */ } vals; far char * ptr; } pointr; pointr.vals.sg= seg; pointr.vals.ofst=offst; return(pointr.ptr); } ____________________________________________________________________ This was off the top of my head, and may be a little off on syntax, but not by much. Hope this is a help. Dan
luis@grinch.UUCP (luis) (11/08/87)
In article <447@ucdavis.ucdavis.edu> kwok@iris.UUCP (Conrad Kwok) writes: >When you are using C, you don't need any special routine to read >memory. All you need to do is to declare a pointer (near or far >depending on the address) and then you may read or write to that >location using normal assignment statements. Here is an example to >read the value at location 0xC000:0x0100 > > char far *ptr; > > ptr = (char far *) 0xC0000100L; > printf("Value at 0xC000:0x0100 is %d\n", *ptr); > >[...] Thank you for posting the example, but I have a few questions... 1. Why is there an 'L' at the end of the address? (does it stand for Long?) 2. I have been trying to access the DTR on my modem, but I don't know what the base address is. From the Technical Reference, I know that the offset is 3FE (bit 0), but can't find the base addres.. Can anyone help? ------------------------------------------------------------------------------- Luis Chanu "Live every day as if it were your last, UUCP: ...ihnp4!sun!aeras!grinch!luis because one day you will be right." UUCP: ...pyramid!wjvax!grinch!luis -Benny Hill Disk-Claimer: That's not your disk, that's my disk. -------------------------------------------------------------------------------
ljz@fxgrp.UUCP (Lloyd Zusman) (11/08/87)
In article <2312@emory.uucp> platt@emory.UUCP (Dan Platt) writes: >In article <24261F3U@PSUVMB> F3U@PSUVMB.BITNET writes: >>I am looking for some functions when called from a C program, will: >> 1) read (peek) memory directly when supplied with >> an address. Returns with the value at specified address. >> and >> 2) write (poke) memory directly when supplied with an >> address and a byte value. >> >>I am using Microsoft C 4.0 on an AT&T 6300 PLUS. Routines >>in C or Assembler OK. There already functions that do this dort of thing in Microsoft C version 4.0 ... void movedata(srcseg, srcoff, destseg, destoff, nbytes) unsigned int srcseg; unsigned int srcoff; unsigned int destseg; unsigned int destoff; unsigned int nbytes; This function copies 'nbytes' bytes of data from srcseg:srcoff to destseg:destoff. If you're in a small- or medium-model program, the 'destseg' parameter can be gotten via the segread() function (it will be the DS register value). But if your really MUST have something like peek and poke, here's a quickly-hacked (i.e., while I'm typing here right now) attempt at these. They're written to work in any memory model. There might be a bug or two, but this is the general idea ... unsigned char peek(segment, offset) unsigned int segment; unsigned int offset; { unsigned char result; unsigned long address = (unsigned long)((char far *)&result); movedata(segment, offset, address >> 16, address & 0x0000ffffL, 1); return (result); } void poke(segment, offset, byte) unsigned int segment; unsigned int offset; unsigned char byte; { unsigned long address = (unsigned long)((char far *)&byte); movedata(address >> 16, address & 0x0000ffffL, segment, offset, 1); } Shorter versions of these could be written ... unsigned char peek(segment, offset) unsigned int segment; unsigned int offset; { unsigned char result; movedata(segment, offset, (char far *)&result, 1); return (result); } void poke(segment, offset, byte) unsigned int segment; unsigned int offset; unsigned char byte; { movedata((char far *)&byte, segment, offset, 1); } However, these shorter versions violate strict typing conventions, as they make use of the fact that a "char far *" takes up the same space on the stack as two unsigned int's (on the PC). A syntax checker like 'lint' wouldn't like this code, nor would many strict-typing purists. I don't remember if the cast should be "char far *" or "char * far", so if this doesn't work, try it the other way. -- Lloyd Zusman, Master Byte Software, Los Gatos, California "We take things well in hand." ...!ames!fxgrp!ljz
kneller@cgl.ucsf.edu (Don Kneller) (11/09/87)
>In article <24261F3U@PSUVMB> F3U@PSUVMB.BITNET writes: >>I am looking for some functions when called from a C program, will: >> 1) read (peek) memory directly when supplied with >> an address. Returns with the value at specified address. >> and >> 2) write (poke) memory directly when supplied with an >> address and a byte value. >> >>I am using Microsoft C 4.0 on an AT&T 6300 PLUS. Routines >>in C or Assembler OK. In MSC it's probably easiest to use the supplied FP_SEG and FP_OFF macros to do this. This works in all memory models: #include <dos.h> unsigned char peek(segment, offset) unsigned int segment, offset; { unsigned char far *cp; FP_SEG(cp) = segment; FP_OFF(cp) = offset; return *cp; } void poke(segment, offset, value) unsigned int segment, offset; unsigned char value; { unsigned char far *cp; FP_SEG(cp) = segment; FP_OFF(cp) = offset; *cp = value; } ----- Don Kneller UUCP: ...ucbvax!ucsfcgl!kneller INTERNET: kneller@cgl.ucsf.edu BITNET: kneller@ucsfcgl.BITNET
flaps@utcsri.UUCP (11/10/87)
In article <447@ucdavis.ucdavis.edu> kwok@iris.UUCP (Conrad Kwok) writes: > char far *ptr; > > ptr = (char far *) 0xC0000100L; > printf("Value at 0xC000:0x0100 is %d\n", *ptr); bad style. avoid temporaries; the reader can't determine (easily) for how long the variable is used. restricting values to an expression, by not storing them in variables, is modular in the same way that restricting values to a function by storing them in local variables is. use instead: printf("contents of C000:0100 is %d\n",*(char far *)0xc0000100L); ajr
gwyn@brl-smoke.ARPA (Doug Gwyn ) (11/10/87)
Use these sparingly! #define PEEK(loc) (*(char *)(loc)) #define POKE(loc,value) *(char *)(loc) = (value) To access a wide datum than a byte, change "char" to "short" or "long".
ljz@fxgrp.UUCP (Lloyd Zusman) (11/11/87)
In article <6662@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: >#define PEEK(loc) (*(char *)(loc)) >#define POKE(loc,value) *(char *)(loc) = (value) This would only work if you are using a large data model and the 'loc' variable is of the type long (or some other 32-bit thing). If you're using Microsoft C version 4.0 (which I believe you are if I don't have you mixed up with another contributor here), use the movedata() function, which I described in a recent posting. It'll work in all memory models. -- Lloyd Zusman, Master Byte Software, Los Gatos, California "We take things well in hand." ...!ames!fxgrp!ljz
kevino@hpccc.HP.COM (Kevin Owen) (11/11/87)
/ hpccc:comp.sys.ibm.pc / luis@grinch.UUCP (luis) / 8:43 pm Nov 7, 1987 / In article <447@ucdavis.ucdavis.edu> kwok@iris.UUCP (Conrad Kwok) writes: >When you are using C, you don't need any special routine to read >memory. All you need to do is to declare a pointer (near or far >depending on the address) and then you may read or write to that >location using normal assignment statements. Here is an example to >read the value at location 0xC000:0x0100 > > char far *ptr; > > ptr = (char far *) 0xC0000100L; > printf("Value at 0xC000:0x0100 is %d\n", *ptr); > >[...] Thank you for posting the example, but I have a few questions... 1. Why is there an 'L' at the end of the address? (does it stand for Long?) 2. I have been trying to access the DTR on my modem, but I don't know what the base address is. From the Technical Reference, I know that the offset is 3FE (bit 0), but can't find the base addres.. Can anyone help? ------------------------------------------------------------------------------- Luis Chanu "Live every day as if it were your last, UUCP: ...ihnp4!sun!aeras!grinch!luis because one day you will be right." UUCP: ...pyramid!wjvax!grinch!luis -Benny Hill Disk-Claimer: That's not your disk, that's my disk. ------------------------------------------------------------------------------- ---------- While I did not post the above response I thought I might take a stab at addressing your questions. You are correct that L indicates long. As for your second question - you need to use inp() and outp() to be able to access your serial port. Both serial and parallel ports on a PC are considered to reside in I/O space and cannot be accessed using memory references. A sample code fragment follows : ------------------------------------ #include <conio.h> unsigned port = 0x3fe; char result; result = inp(port); /* Result now contains the byte input from port 3fe */ printf("DTR is %s\n",(result & 0x01) ? "HIGH" : "LOW"); ------------------------------------ I hope this helps... Regards, Kevin Owen
michael@orcisi.UUCP (11/11/87)
> union { > struct { > short: ofst,sg; /* these may be backwards */ > } vals; > far char * ptr; > } pointr; > > pointr.vals.sg= seg; > pointr.vals.ofst=offst; The MSC FP_OFF and FP_SEG macros supplied in one of the standard header files might be used here instead. Their are valid as both rvalues and lvalues.
rab@mimsy.UUCP (Bob Bruce) (11/12/87)
Followup-To: In article <261@grinch.grinch.UUCP> luis@grinch.UUCP (Luis Chanu) writes: >In article <447@ucdavis.ucdavis.edu> kwok@iris.UUCP (Conrad Kwok) writes: >> ... >> ptr = (char far *) 0xC0000100L; > > 1. Why is there an 'L' at the end of the address? (does it stand for Long?) Yes, it stands for long. Many compilers have 32 bit pointers and 16 bit int's. Appending an `L' to a constant is equivalent to casting it to a long. In an assignment, such as this, the `L' is not necessary, but it does emphasize that the constant is bigger than an int. > 2. I have been trying to access the DTR on my modem, but I don't know > what the base address is. From the Technical Reference, I know that > the offset is 3FE (bit 0), but can't find the base address. Can anyone > help? Sorry, but the 3FE is a port address, not a memory location. Check your compiler manual. It should provide some library routines for accessing I/O ports. Usually something like `outp()' and `inp()'. If these are not provided then you are going to have to write some assembly language routines.
moran@yale.UUCP (11/12/87)
From personal experience, when doing things like getting at ports (i.e. doing modem control stuff), it's better to use assembly language, and interrupts than to try to munge it out in C. William L. Moran Jr. moran@{yale.arpa, cs.yale.edu, yalecs.bitnet} ...{ihnp4!hsi,decvax}!yale!moran "The treatment lasts one second, but the effects last your lifetime." "Have you ever had a Pan-Galactic gargleblaster?" "This is worse!" "Freeowww!!" -Hitch Hiker's Guide Radio Series
mac3n@babbage.acc.virginia.edu (Alex Colvin) (11/13/87)
> #define PEEK(loc) (*(char *)(loc)) > #define POKE(loc,value) *(char *)(loc) = (value) > > To access a wide datum than a byte, change "char" to "short" or "long". These will work in SOME program models with SOME compilers. In the small model, a (char *) can only point within the data segment. What's probably wanted here is a pointer that can reach anywhere in memory. Because this issue isn't well defined by PDP-11 C, most PC compilers have their own way of doing this. In CII's C86 there is the movblock routine, whose arguments are offsets and segments. In uSoft C you can declare (char far*) pointers, which can point outside your data segment. Casting (loc) to a pointer is unreliable. The meaning of a such a cast is not well-defined. If loc is a 16-bit int or short, this won't get you beyond the data segment, but is probably reliable for references (offsets) within it. If loc is a 32-bit int or long (depends on your compiler), it can hold a full address. Now the question is, what's an address? Some compilers view such a cast as a simple trick on the type system, in which case (loc) should consist of a segment in the most significant 16 bits and an offset in the least significant 16 (the actual format of a far pointer). Other compilers try to make casts into conversions, and assume (loc) is a 32-bit offset from the beginning of memory, in which case (loc) has the segment number * 16 + the offset, in 32 bits. Best to find out what your compiler manual tells you. Then decorate the code with warnings and #ifdefs been burned before... mac@cs.virginia.edu
tainter@ihlpg.ATT.COM (Tainter) (11/13/87)
In article <5640@utcsri.UUCP>, flaps@utcsri.UUCP writes: > bad style. avoid temporaries; the reader can't determine (easily) for [ deletions ] > use instead: > printf("contents of C000:0100 is %d\n",*(char far *)0xc0000100L); > ajr OR, if that is too cryptic for your tastes use: function() { otherstuff; { /* restrict the scope of ptr */ char far *ptr; ptr = (char far *) 0xC0000100L; printf("Value at 0xC000:0x0100 is %d\n", *ptr); } morestuff; } --j.a.tainter
greg@gryphon.CTS.COM (Greg Laskin) (11/14/87)
>In article <24261F3U@PSUVMB> F3U@PSUVMB.BITNET writes: >>I am looking for some functions when called from a C program, will: >> 1) read (peek) memory directly when supplied with >> an address. Returns with the value at specified address. >> and >> 2) write (poke) memory directly when supplied with an >> address and a byte value. >> >>I am using Microsoft C 4.0 on an AT&T 6300 PLUS. Routines >>in C or Assembler OK. In Mircrosoft C: foo() { char huge *blat =0; char far *p; char c; int i; /* assume n is the ABSOLUTE address of an object in physical memory -- linear space, not segmented */ long n = 0x0c0000; c = blat[n]; i = ((int huge *)blat)[n]; /* huge pointers are EXPENSIVE so if you're going to do lots of stuff in a 64K segement, like video stuff, resolve the address into a far pointer and use it instead thusly */ p = &blat[0xb8000]; } Note: #ifndef M_LGDATA #define huge #define far #endif to remove the processor dependency of the code. (Yes. I know about the non-portability of the hard addressing) -- Greg Laskin "When everybody's talking and nobody's listening, how can we decide?" INTERNET: Greg.Laskin@gryphon.CTS.COM UUCP: {hplabs!hp-sdd, sdcsvax, ihnp4}!crash!gryphon!greg UUCP: {philabs, scgvaxd}!cadovax!gryphon!greg
gwyn@brl-smoke.ARPA (Doug Gwyn ) (11/17/87)
In article <127@babbage.acc.virginia.edu> mac3n@babbage.acc.virginia.edu (Alex Colvin) writes: >> #define PEEK(loc) (*(char *)(loc)) >Some compilers view such a cast as a simple trick on the type system, ... >Other compilers try to make casts into conversions ... In C, a cast IS a conversion. However, you're right in remarking that some compilers have gotten this wrong. It is also true that conversion between a pointer and an integer of the proper size is implementation specific, although I would hope that an implementation that supports this at all would document the mapping. Portable applications will not resort to such tricks in the first place..