I have two 68000 registers A2 and A7. Initially A2 contains $002C4178 and A7 contains $0000A000. Then, the following instructions execute in sequence:
MOVE.L #6,-(A2)
MOVE.L #14,-(A7)
MOVE.L #$24,(A7)
MOVE.L (A7),$1000
What are the contents of the changed memory? What are the contents of the registers A2 and A7 (in hex)?
A2 is pre-decremented in the first instruction, so:
$002C4178 => $002C4174
then #6 is stored at this address.
Then A7 is pre-decremented, so:
$0000A000 => $00009FFC
then #14 is stored at this address. This is then immediately overwritten by the next instruction, which writes #$24 (#36) at the same address.
Finally the value above in the location pointed at by A7 (#$24) is stored at absolute address $1000.
Related
I have the following simple COBOL program - written for the PC. It simply reads a file from the computer and writes to the file:
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT CUSTOMER-FILE ASSIGN TO
"C:Customers.dat"
ORGANIZATION IS LINE SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD CUSTOMER-FILE.
01 CUSTOMER-RECORD.
05 FIRST-NAME PIC X(20).
05 LAST-NAME PIC X(20).
WORKING-STORAGE SECTION.
01 WS-CUSTOMER-RECORD.
05 WS-FIRST-NAME PIC X(20).
05 WS-LAST-NAME PIC X(20).
01 WS-EOF PIC X.
PROCEDURE DIVISION.
OPEN OUTPUT CUSTOMER-FILE
PERFORM UNTIL CUSTOMER-RECORD = SPACES
DISPLAY "Enter the first and last name for the customer"
ACCEPT CUSTOMER-RECORD
WRITE CUSTOMER-RECORD
END-PERFORM
CLOSE CUSTOMER-FILE
DISPLAY "Output from the Customer File:"
OPEN INPUT CUSTOMER-FILE.
PERFORM UNTIL WS-EOF = 'Y'
READ CUSTOMER-FILE INTO WS-CUSTOMER-RECORD
AT END MOVE 'Y' TO WS-EOF
NOT AT END DISPLAY WS-CUSTOMER-RECORD
END-READ
END-PERFORM.
CLOSE CUSTOMER-FILE.
GOBACK.
My question: I'm not too familiar with JCL. So if I were to put this program on a mainframe, what would I do for the JCL?
I presume your Identification Division got lost in a cut & paste incident on its way to Stack Overflow; you'll need that.
The current incarnation of IBM Enterprise COBOL does not allow free format source so in order to get your code to compile you would have to reformat and follow the traditional fixed format.
Rather than referring to your data file by name, your Assign clause must refer to a name (limited to 8 characters) which corresponds to a DD name in your JCL. Pick something meaningful, to the extent you can in 8 characters, maybe CUSTOMER.
Since you're running with JCL, your Accept statement will work a bit differently. Probably data will come from a SYSIN DD.
Your JCL will look something like this...
[job card, which is shop-specific]
//TOMSPGM EXEC PGM=yourProgramName
//STEPLIB DD DISP=SHR,DSN=mainframe.dataset.where.you.bound.your.program
//SYSIN DD *
[your customer records]
//CUSTOMER DD DISP=(NEW,CATLG,DELETE),
// DSN=mainframe.dataset.where.your.data.should.end.up,
// LRECL=40,
// AVGREC=U,
// RECFM=FB,
// SPACE=(40,(10,10),RLSE) Adjust to your needs
//SYSOUT SYSOUT=*
//CEEDUMP SYSOUT=*
I'm not sure how this will work with your creating the customer file and then reading it in the same program. In 30 years of mainframe work I've never seen that.
Adding to answer from #cschneid.
Great to see AVGREC is being used on the DD statement to allocate space for the data set. This is much better than using the old-fashioned CYL, or TRK units.
Unfortunately, IMHO, the IBM z/OS architects missed to implement a more modern was to specify space: KiB, or MiB. (ISPF supports KB, and MB as space unit, JCL doesn't.)
With AVGREC you tell the system that the SPACE= primary and secondary space values are number of records, instead of physical units such as tracks, or cylinders.
//CUSTOMER DD ...
// AVGREC=U,
// SPACE=(40,(10,20),RLSE)
Above statement tells the system that the records written will have an average length of 40 bytes (this completely is independent of RECFM=, or LRECL=!). With AVGREC=U (U means units), this further tells the system to allocate initial (primary) space for 10 records, and to add additional space for 20 records each time more space is needed (with an upper limit).
Physical allocations are still in tracks, or cylinders under the hood. The system calculates tracks, or cylinders needed from
"average record length" * "number of records" * avgrec-unit
For the primary allocation, this is
40 * 10 * 1 = 400 bytes
Good. But how can we specify our space needs in KiB or MiB using these keywords?
Remember that the average record length in the SPACE= parameter is completely unreleated to the actual record length specified via LRECL=. Great, so we can freely choose the average record length, and set it to, say, 1. And let us also change the wording "number of records* in above forumla to "number of units". The formula becomes:
1 * "number of units" * avgrec-unit
or
"number of units" * avgrec-unit
AVGREC= supports the units U (1), K (1024), and M (1024*1024). So, to allocate space in megabytes (MiB), we simply code:
//CUSTOMER DD ...
// AVGREC=M,
// SPACE=(1,(10,20),RLSE)
This will allocate 10 MiB primary space, and 20 MiB secondary space. Each allocation is rounded up to the next integral number of tracks, or cylinders, depending on physical disk structures. You simply don't have to care anymore. Neat, isn't it?
I have a common C function that I want to call from C, Fortran and COBOL. It fetches x bytes of data from a database and places it in a char pointer supplied to it. My example below fetches 1024 bytes, but in the real situation I want to be able to fetch much larger chunks of data than 1024 bytes as well, hence the dynamic memory allocation.
void fetch_data(char *fetched)
{
static struct {unsigned long data_length; char some_data[1024];} a_struct;
// Fetch data into a_struct.
memcpy(fetched, &(a_struct.some_data), 1024);
}
I was able to call this function successfully from C.
char *mydata;
mydata = malloc(1024);
fetch_data(mydata);
// Do something with the data.
free(mydata);
I was also able to call this function successfully from Fortran.
INTEGER*4, ALLOCATABLE :: MYDATA(:)
ALLOCATE(MYDATA(1024))
CALL FETCH_DATA(MYDATA)
// Do something with the data.
DEALLOCATE(MYDATA)
But how do I allocate and deallocate dynamic memory in COBOL? I have been unable to find built-in functions/procedures for this purpose.
I also don't see an alternative where C could handle the allocation and deallocation for Fortran and COBOL, as they need to access the data outside C.
As you've only talked about "COBOL" without specifying any actual implementation I assume you mean "standard COBOL".
This could mean COBOL85 - which doesn't have this feature but allows you to just define DATA-FOR-C PIC X(1024) and pass this as reference (COBOL85 actually doesn't specify anything about calling into C space but this should work with most if not all COBOL implementations). Note: This is actually more a detail of Acorns answer.
If you want to use real dynamic memory allocation and you mean standard COBOL - no problem with COBOL 2002 as it introduced the statements ALLOCATE and FREE (Note: this is actually the detail of the comments from roygvib and Rick):
77 pointer-variable USAGE POINTER.
77 address-holder PIC X BASED.
ALLOCATE variable-number CHARACTERS RETURNING pointer-variable
SET ADDRESS OF address-holder TO pointer-variable
CALL "fetch_data" USING address-holder
PERFORM stuff
FREE pointer-variable
If you don't use a COBOL implementation that support these statements you'd have to use the implementor specific routines (normally via CALL) to get/release the memory.
MicroFocus/NetCOBOL (see answer of Rick): CBL_ALLOC_MEM/CBL_FREE_MEM[2]
ACUCOBOL: M$ALLOC/M$FREE
IBM: CEEGTST
any COBOL compiler and runtime that allows to directly call C functions (which may adds additional needs as specifying the appropriate CALL-CONVENTION for those): malloc/free
... see your implementor's manual ...
One example with a very old compiler (Micro Focus COBOL v3.2.50). Much of this is taken directly from the supplemental materials. And since I didn't have an equally old C compiler available, I included a COBOL program as a subtitute.
program-id. dynam.
data division.
working-storage section.
1 ptr pointer.
1 mem-size pic x(4) comp-5 value 1024.
1 flags pic x(4) comp-5 value 1.
1 status-code pic x(2) comp-5.
linkage section.
1 mem pic x(1024).
procedure division.
call "CBL_ALLOC_MEM" using ptr
by value mem-size flags
returning status-code
if status-code not = 0
display "memory allocation failed"
stop run
else
set address of mem to ptr
end-if
call "fetch_data" using mem
display mem
call "CBL_FREE_MEM" using mem
returning status-code
if status-code not = 0
display "memory deallocation failed"
stop run
else
set address of mem to null
end-if
stop run
.
end program dynam.
program-id. "fetch_data".
data division.
working-storage section.
1 some-struct pic x(1024) value all "abcd".
linkage section.
1 mem pic x(1024).
procedure division using mem.
move some-struct to mem
exit program
.
end program "fetch_data".
The display (trimmed) is:
abcdabcdabcdabcd...(for 1024 characters total)
Maybe that will be of some help.
If you do not need the entire data in memory, then consider working chunk-by-chunk: allocate fixed-size storage in COBOL, fetch a chunk into it using the C function, work with it and loop to continue with the next chunk. This way you can avoid allocating dynamic memory altogether.
If you are on Z or using Gnu Cobol you can simply call malloc():
CALL "malloc" USING BY VALUE MEM-SIZE
RETURNING MEM-PTR.
CALL "free" USING BY VALUE MEM-PTR.
The following page table is for a system with 16-bit virtual and physical addresses and with 4,096-byte pages. The reference bit is set to 1 when the page has been referenced. Periodically, a thread zeroes out all values of the reference bit.All numbers are provided in decimal.
I want to convert the following virtual addresses (in hexadecimal) to the equivalent physical addresses. Also I want to set the reference bit for the appropriate entry in the page table.
• 0xE12C
• 0x3A9D
• 0xA9D9
• 0x7001
• 0xACA1
I know the answers are but I want to know how can I achieve these answers:
0xE12C → 0x312C
0x3A9D → 0xAA9D
0xA9D9 → 0x59D9
0x7001 → 0xF001
0xACA1 → 0x5CA1
I found and tried This but it did not help me much.
It is given that virtual address is 16 bit long.Hence, there are 2^16 addresses in the virtual address space.
Page Size is given to be 4 KB ( there are 4K (4 * (2 ^ 10) )addresses in a page), so the number of pages will be ( 2^16 ) / ( 2 ^ 12 ) = 2 ^ 4.
To address each page 4 bits are required.
The most significant 4 bits in the virtual address will denote the page number being referred and the remaining 12 bits will be the page offset.
One thing to remember is page size (in the virtual address space ) is always same as the frame size in the main memory. Hence the last 12 bits will remain same in the physical address as that of the virtual address.
To get the frame address in the main memory just use the first 4 bits.
Example: Consider the virtual address 0xACA1
Here A in ACA1 denotes the page number ( 10 ) and corresponding frame no is 5 ( 0101) hence the resulting physical address will be → 0x5CA1.
To translate a virtual address to a physical address (applies ONLY to this homework question), we need to know 2 things:
Page Size
Number of bits for virtual address
In this example: 16-bit system, 4KB page size and physical memory size is 64KB.
First of all we need to determine the number of needed bits to act as offset inside page. log2(Page-Size) = log2(4096) = 12 bits for offset
Out of the 16 bits for virtual address, 12 are for offset, that means each process has 2^4 = 16 virtual pages. Each entry in page table stores the corresponding frame accommodating the page. For example:
Now lets translate!
First of all for ease of work lets convert 0xE12C to binary.
0xE12C = (1110 0001 0010 1100) in base 2
1110 = 14 in decimal
Entry 14 in P.T => Page frame 3.
Lets concatenate it to the 12 offset bits
Answer: (0011 0001 0010 1100) = 0x312C
Another example: 0x3A9D
0x3A9D = 0011 1010 1001 1101
0011 = 3
PageTable[3] = 10
10 in decimal = 1010 in binary
1010 1010 1001 1101 in binary = 0xAA9D
To help you solve this question, we need to get our details right:
16 bit of virtual address space = 2^16 = 65,536 address space
16 bit of physical address space = 2^16 = 65,536 address space
4096 Byte page size determines the offset, which is Log(4096) / Log (2) = 12 bit. This means, 2^12 for Page size
As per #Akash Mahapatra, the offset from virtual address is directly mapped to the offset onto physical address
As such, we now have:
2^16 (16bit) for virtual address - 2^12 (12bit) for offset = 4-bit for pages, or rather total number of pages available.
I won't repeat the calculation for physical since it's the same numbers.
2^4 (4bit) for pages = 16, which correlates to the number of table entries above!
We're getting there... be patient! :)
Memory Address 0xE12C in hex notation is also known to be holding 16-bit of address. (Since it's stated in the question.)
Let's butcher the address now...
We first remove '0x' from the info.
We can convert E12C to binary notation like #Tony Tannous, but I am going to apply a little short-cut.
I simply use a ratio. Well, the address is notated in 4 characters above, and since 16/4 = 4, I can define the first letter as virtual address, while the other 3 are offset address.
With the information, 'E' in hexadecimal format, I need to convert to Decimal = 14. Then I look at your table provided, and I found page frame '3'. Page frame 3 is noted in decimal format, which then need to be converted back to Hexadecimal format... Duh!... which is 3!
So, the Physical address mapping of the virtual memory location of 0xE12C can be found at 0x312C on the physical memory.
You will then go back to the table, and refer to the reference bit column and put a '1' to the row 14.
Apply the same concept for these -
0x3A9D → 0xAA9D
0xA9D9 → 0x59D9
0x7001 → 0xF001
0xACA1 → 0x5CA1
If you notice, the last 3 digits are the same (which determines the offset).
And the 1st of the 4-digits are mapped according to the table:
table entry 3 -> page frame 10 -> hex notation A
table entry A (10) -> page frame 5 -> hex notation 5
table entry 7 -> page frame 15 -> hex notation F
table entry A (10) -> page frame 5 -> hex notation 5
Hope this explanation helps you and others like me! :)
A year ago, we analyzed with SPSS 22 some data with 100+ variables on 5 lines. We used the GUI and laboriously entered variable names and output formats. This year, we are using SPSS 23 after a mandatory upgrade. We have similar data, and want to use a syntax file instead. We copied the GET DATA output from last year, made a few changes, and ran. No deal. We get the notorious and almost completely unhelpful error message in the title. (It continues "The format is invalid. For numeric formats, the width or decimals value may be invalid." Not line number, Not indication of the problem).
We are not using big numbers. We are not using macros, as in this SO question. We tried replacing F1.0 with N1. There are no ','s in the file (hence, no F3,1-like typos). I have searched the web. Does anyone know what else the problem might be?
The failing GET DATA statement, with filename and middle elided.
GET DATA /TYPE=TXT
/FILE="E: ... .txt"
/ENCODING='UTF8'
/DELCASE=VARIABLES 123
/DELIMITERS="\t"
/ARRANGEMENT=DELIMITED
/FIRSTCASE=1
/IMPORTCASE=ALL
/VARIABLES=
ID A4
Group A2
Quality A2
V4 A5
oarea F4.1
oallarea F4.1
olthmean F5.3
olthmax F5.3
...
x N1
o N1
S N1
Z N1
w N1.
F5.5 was not valid. Fixing that and program ran.
I built an assembly program using mpasm for the pic 10f322, and I want the program to read off all characters in my TABLE: by placing these values back into my WREG. When my code executes, it is suppose to read off the value stored in register FSR and fetch the value stored at the address pointed to. This FSR value then increments to get the next character. However, when I run the program, the pointer is incrementing correctly but the code is grabbing junk values since there doesn't seem to be any values stored in memory. Why are my directives not working?
org 0x0000
FSR Equ 0x04
INDF Equ 0x00
START
movlw TABLE
movwf FSR ; move w value int address FSR
Loop: movf INDF, 0 ; move character pointed in table back to w reg
incf FSR ; increment incfg
goto Loop
TABLE:
db "HELLO"
db "Man"
END
I don't want data to be stored in program memory. Instead I would like to put data in data memory. Are there assembly directives that allow me to do this easily like DB? My assembler is MPASM.
You can not access the code memory via FSR and INDF registers, this two registers are intended to access data memory.
Use lookup table instead:
movlw 1 ;Read second byte in Table
movwf TableIndex ;Store index
call ReadLookupTable ;Perform table read
...
ReadLookupTable
movlw high Table
movwf PCLATH
movlw low Table
addwf TableIndex, w ;Add index to table pointer
movwf PCL ;Perform computed jmp
Table
retlw 10
retlw 11
...